denoland/deno
ext/web
Active contributors: Bartek Iwańczuk, Divy Srivastava, Marvin Hagemeister
Purpose
ext/web is the foundational web platform extension. It implements the DOM-style globals that have nothing to do with networking or the filesystem: events, abort signals, message ports, structured clone, blobs, file readers, base64, text encoding, streams, the URL constructor, the URL pattern matcher, performance API, and the timer functions. Most other web platform extensions (ext/fetch, ext/websocket, ext/webstorage) depend on ext/web for their primitives.
Directory layout
ext/web/
├── Cargo.toml
├── lib.rs # extension!() macro, ops registration
├── 00_infra.js # primordials, basic infra
├── 00_url.js # URL parsing
├── 01_broadcast_channel.js
├── 01_console.js # console.* implementation
├── 01_dom_exception.js # DOMException
├── 01_mimesniff.js # MIME sniffing
├── 01_urlpattern.js # URLPattern
├── 02_event.js # EventTarget, Event, CustomEvent
├── 02_structured_clone.js # structuredClone()
├── 02_timers.js # setTimeout / setInterval / queueMicrotask
├── 03_abort_signal.js # AbortController / AbortSignal
├── 04_global_interfaces.js # WindowOrWorkerGlobalScope shared
├── 05_base64.js # atob / btoa
├── 06_streams.js # ReadableStream, WritableStream, TransformStream
├── 06_streams_types.d.ts
├── 08_text_encoding.js # TextEncoder / TextDecoder
├── 09_file.js # Blob, File
├── 10_filereader.js # FileReader
├── 12_location.js # Worker location
├── 13_message_port.js # MessageChannel, MessagePort
├── 14_compression.js # CompressionStream, DecompressionStream
├── 15_performance.js # performance.now(), PerformanceObserver
├── 16_image_data.js # ImageData
├── blob.rs, broadcast_channel.rs, compression.rs, console.rs,
│ css_value.rs, f64.rs, geometry.rs, message_port.rs,
│ stream_resource.rs, timers.rs, url.rs, urlpattern.rs # ops
├── benches/
└── webtransport.js # WebTransport (in-progress)The 24 *.js files are loaded in numeric order during snapshot creation, so something at 02_* can rely on 00_* and 01_* having already defined their globals.
Key abstractions
| Type | Where | Role |
|---|---|---|
BlobStore |
blob.rs |
In-memory store backing Blob/File/object URLs; passed into worker construction |
InMemoryBroadcastChannel |
broadcast_channel.rs |
Backs BroadcastChannel when not crossing process boundaries |
MessagePort resource |
message_port.rs |
Half of a port pair backing MessageChannel and Worker.postMessage |
stream_resource |
stream_resource.rs |
Bridge between Rust AsyncRead/AsyncWrite and ReadableStream/WritableStream |
urlpattern ops |
urlpattern.rs |
Parser/matcher for URLPattern |
compression ops |
compression.rs |
gzip/deflate streams (via flate2) |
timers ops |
timers.rs |
setTimeout / setInterval backed by Tokio |
console ops |
console.rs |
Minimal native helpers; bulk of console.* is in 01_console.js |
How it works
graph LR
UserCode["fetch(url) / new Blob(...) / setTimeout(...)"] --> JsFiles["ext/web/*.js<br/>(numbered, snapshotted)"]
JsFiles -->|core.ops.op_*| Ops["ext/web/*.rs<br/>#[op2]"]
Ops --> Tokio["Tokio runtime"]
Ops --> BlobStore[("BlobStore")]
Ops --> Streams["stream_resource bridge"]
Streams --> Rust["AsyncRead / AsyncWrite"]Streams
06_streams.js (the largest file in this extension) implements ReadableStream, WritableStream, and TransformStream per the WHATWG spec — including byob byte streams, queueing strategies, and tee'ing. The Rust side (stream_resource.rs) is a shim that lets ops produce or consume streams without each op re-implementing the buffering protocol.
Timers
02_timers.js exposes setTimeout, setInterval, setImmediate, and queueMicrotask. The actual scheduling lives in timers.rs using Tokio's timer wheel; the JS layer is mostly responsible for the v8-side bookkeeping (handle ids, ref/unref).
MessagePort
message_port.rs + 13_message_port.js implement the MessageChannel/MessagePort primitives. They're the same primitives Worker uses internally for postMessage. The Rust side owns the cross-thread MPSC channel; the JS side wraps it in event-emitter semantics.
URL and URLPattern
url.rs + 00_url.js implement the URL spec on top of the url crate, plus origin/host/pattern helpers. urlpattern.rs + 01_urlpattern.js implement the URLPattern spec used by Deno.serve for routing.
Integration points
- Depended on by:
ext/fetch,ext/websocket,ext/webstorage,ext/webgpu,ext/cache,ext/http(for streams + AbortSignal), and parts ofext/node(which re-exposes web globals to Node code). - Depends on:
ext/webidlfor type conversion (webidl::convert<...>(...)calls),deno_coreprimordials. - Worker integration:
BlobStoreandInMemoryBroadcastChannelare constructed by the CLI / runtime caller and passed intoMainWorker::bootstrap_from_options.
Entry points for modification
- New web API global — pick the appropriate numbered slot, add a
*.jsfile, define ops in a*.rssibling, register both inlib.rs'sextension!()macro. - Stream behavior — most logic is in
06_streams.js; the Rust shim instream_resource.rsis mostly stable. - URL spec update —
url.rs(URL crate version) plus00_url.js. URLPattern is split out intourlpattern.rs/01_urlpattern.js. structuredClonetypes —02_structured_clone.jsplus the message-port serializer in13_message_port.js.
Key source files
| File | Purpose |
|---|---|
ext/web/lib.rs |
deno_core::extension!() registration of ops + JS |
ext/web/06_streams.js |
WHATWG Streams implementation (largest single JS file) |
ext/web/stream_resource.rs |
Bridge between Rust AsyncRead/Write and JS streams |
ext/web/timers.rs + 02_timers.js |
setTimeout/setInterval |
ext/web/message_port.rs + 13_message_port.js |
MessagePort/Channel |
ext/web/blob.rs + 09_file.js + 10_filereader.js |
Blob/File/FileReader |
ext/web/url.rs + 00_url.js + urlpattern.rs + 01_urlpattern.js |
URL + URLPattern |
ext/web/02_event.js |
EventTarget / Event / CustomEvent |
ext/web/03_abort_signal.js |
AbortController / AbortSignal |
ext/web/06_streams_types.d.ts |
Type declarations for streams (used by editor tooling) |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.