denoland/deno
Extensions
Active contributors: Bartek Iwańczuk, Divy Srivastava, Yoshiya Hinosawa, Marvin Hagemeister
The ext/ directory contains 31 self-contained crates, one per "extension". An extension bundles a slice of Rust ops with the JS that exposes them to user code: Deno.openSync lives in ext/fs, fetch() lives in ext/fetch, WebSocket lives in ext/websocket, and so on.
Each extension is registered with the runtime by runtime/lib.rs and instantiated during worker construction in runtime/worker.rs and runtime/web_worker.rs.
What an extension actually is
graph LR
subgraph Ext["ext/<name>/ — one extension crate"]
Cargo["Cargo.toml"]
LibRs["lib.rs<br/>deno_core::extension!()"]
Ops["*.rs<br/>#[op2] fn op_*"]
Js["*.js<br/>user-visible API"]
end
LibRs -->|registers| OpReg["ops: [op_a, op_b, …]"]
LibRs -->|registers| JsReg["esm: [01_foo.js, 02_bar.js]"]
Ops -->|callable from| Js
Js -->|exposed as| Globals["globalThis.fetch / Deno.* / etc"]
Runtime["runtime/lib.rs"] --> LibRsConventions:
lib.rscalls thedeno_core::extension!(name = ..., ops = [...], esm_entry_point = "...", esm = [...])macro.- Op functions use
#[op2]fromdeno_coreand live in eitherlib.rsor sibling*.rsfiles. - JS files are numbered (
00_*,01_*, …) to control snapshot load order. - A
README.mdper extension typically points to the user-visible API doc page.
The full list
Every ext/<name>/ is a standalone Cargo crate. Counts below are at the snapshot date.
Web platform APIs
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/web |
Collection of Web APIs (URL, Event, AbortController, streams, MessagePort, base64, timers, performance, …) | 13 | 24 |
ext/fetch |
fetch, Request, Response, Headers, FormData |
5 | 8 |
ext/websocket |
WebSocket, WebSocketStream |
2 | 2 |
ext/webstorage |
localStorage / sessionStorage |
1 | 1 |
ext/webidl |
WebIDL type conversions used by other extensions | 1 | 1 |
ext/webgpu |
WebGPU bindings (largest in terms of Rust at 23 files) | 23 | 3 |
ext/url |
Deprecated; use deno_web |
1 | 0 |
ext/console |
Deprecated; use deno_web |
1 | 0 |
ext/broadcast_channel |
Deprecated; use deno_web |
1 | 0 |
ext/crypto |
WebCrypto (SubtleCrypto, crypto.randomUUID, …) |
11 | 1 |
Filesystem, network, OS
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/fs |
Deno.open, Deno.readFile, watch APIs |
4 | 1 |
ext/net |
TCP/UDP/Unix sockets (Deno.listen, Deno.connect) |
11 | 3 |
ext/http |
HTTP server primitives (powers Deno.serve) |
10 | 1 |
ext/tls |
TLS for net and http |
3 | 0 |
ext/io |
IO primitives (stdin/stdout, resource tables) | 6 | 1 |
ext/os |
OS APIs (hostname, env-aware paths, Deno.osRelease) |
2 | 2 |
ext/process |
Subprocess APIs (Deno.Command, child_process core) |
2 | 1 |
ext/signals |
Signal handling (Deno.addSignalListener) |
2 | 0 |
Node.js compatibility
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/node |
The big one: node:* polyfills (in polyfills/) plus core ops |
2 (+ many in subdirs) | many in polyfills/ |
ext/node_crypto |
Splits Node's crypto layer out of ext/node |
10 | 0 |
ext/node_sqlite |
node:sqlite polyfill |
8 | 0 |
Deno-specific
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/kv |
Deno.openKv() — built-in KV store |
6 | 0 |
ext/cron |
Deno.cron() scheduled jobs |
5 | 0 |
ext/cache |
Web Cache API (caches.open) |
4 | 1 |
ext/bundle |
The bundle subcommand's runtime API hooks | 0 | 0 |
ext/rt_helper |
Helpers for denort (the binary used by deno compile) |
1 | 0 |
ext/telemetry |
OpenTelemetry exporter for spans/metrics/logs | 2 | 0 |
Native code interop
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/ffi |
Deno.dlopen (call into shared libraries) |
9 | 1 |
ext/napi |
Node-API native addons | 8 | 0 |
Misc
| Crate | Description | Rust files | JS files |
|---|---|---|---|
ext/image |
Image decoding / ImageData / ImageBitmap |
3 | 1 |
Detail pages
Three of the largest extensions have their own deeper page:
ext/web— the kitchen-sink web platform crate; touches almost every JS file you'll find underruntime/js/and is the foundation for every other web API extensionext/node— the Node.js compatibility surface; thousands of lines of polyfills, the core of hownpm:packages run on Denoext/fs— the filesystem extension; canonical example of the op-pattern + permission integration
For the rest of the extensions, the README in each ext/<name>/ plus the lib.rs are the entry points.
How to add a new op
- Pick the right extension. New web APIs go in
ext/web. New filesystem APIs inext/fs. Node polyfills inext/node/polyfills/<module>.ts. - Add an
#[op2]Rust function in a sibling*.rsfile:#[op2(async)] pub async fn op_my_new_thing( state: Rc<RefCell<OpState>>, #[string] arg: String, ) -> Result<i32, AnyError> { ... } - Register it with the extension macro in
lib.rs:deno_core::extension!( deno_my_ext, ops = [op_my_new_thing, /* …existing ops… */], esm = ["00_my_ext.js"], … ); - Use it from JS:
const { op_my_new_thing } = core.ops; export async function myNewThing(arg) { return await op_my_new_thing(arg); } - Add the user-facing JS API to a numbered file, then expose it via the bootstrap (
runtime/js/) if needed. - If the op does anything privileged, add a
state.borrow_mut::<PermissionsContainer>().check_*(...)call. - Add a unit test under
tests/unit/.
How to add a new extension
Rare, but if you must:
cargo new --lib ext/my_ext- Add the new directory to the workspace
memberslist in the top-levelCargo.toml. - Pattern your
lib.rsafter a small existing extension (e.g.,ext/cacheorext/cron). - Add
pub use deno_my_ext;toruntime/lib.rs. - Register the extension in
runtime/worker.rsandruntime/web_worker.rsby addingdeno_my_ext::deno_my_ext::init_ops_and_esm(...)to the extension list. - Test it with a unit test or spec test.
See Patterns and conventions for the op signature conventions.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.