esrun's global scope tracks the WinterTC Minimum Common Web Platform API. These are standard Web globals — the same names you would use in a browser or other server runtimes. Host capabilities (filesystem, process, network access) are not globals; they live in runtime: modules.
Core
Global
Notes
globalThis
self
console
full Console Standard set — see below
queueMicrotask
structuredClone
reportError
navigator
userAgent — "ES-Runtime/<version>"; hardwareConcurrency — the CPU count a worker pool is sized from
console
Group
Methods
Output
log, info, warn, error, debug, dir, dirxml, trace
Grouping
group, groupCollapsed, groupEnd
Counting
count, countReset
Timing
time, timeLog, timeEnd
Other
assert, table, clear
Format specifiers: %s, %d/%i, %f, %o/%O, %j, %%, %c.
A failure with nothing left to catch it is offered to the global scope first. preventDefault() claims it; anything unclaimed is printed and exits non-zero.
Event
Fired when
Cancelable
error
an exception escapes a timer callback, or reportError()
yes
unhandledrejection
a rejection is unhandled at the end of a tick
yes
rejectionhandled
a handler attaches to an already-reported rejection
no
JavaScript
globalThis.addEventListener("unhandledrejection", (event) => {
logger.warn("unhandled", event.reason);
event.preventDefault(); // mine now — do not fail the process
});
onerror / onunhandledrejection / onrejectionhandled are single-handler slots over the same events. rejectionhandled does not retract a report that has already gone out.
Messaging
Messages are structured-cloned at postMessage, delivered in order, and reach other agents — a worker is a second isolate on its own thread. See Workers.
Global
Notes
Worker
module workers only; starts with no capabilities, granted per spawn; { memory } caps its heap
MessageChannel / MessagePort
a port buffers until start(); assigning onmessage starts it
BroadcastChannel
reaches every open channel of the same name except itself, in creation order
A MessagePort may be transferred and may not be cloned — two ends of a channel cannot become three — and arrives through event.ports. ArrayBuffer and streams transfer too; a SharedArrayBuffer is shared rather than transferred, which is what makes Atomics between agents mean anything.
Inside a worker the global scope is a DedicatedWorkerGlobalScope, with WorkerNavigator and WorkerLocation alongside it.
Data
Global
Notes
Blob
File
FormData
DOMException
Performance
Global
Notes
performance
now(), timeOrigin, User Timing (mark/measure/getEntries*/clear*)
Passing a ReadableStream as the fetch body uploads it as a chunked transfer with backpressure — the body is never fully buffered, so large or open-ended uploads stay memory-bounded. Response bodies stream too.
JavaScript
// A ReadableStream body streams to the server (chunked upload, backpressured).
const body = new ReadableStream({
async pull(c) {
const next = await source.read(); // your data source
if (next.done) c.close();
else c.enqueue(next.value); // Uint8Array chunks
},
});
await fetch("https://example.com/upload", { method: "POST", body });
// Anything else (string, Blob, FormData, Uint8Array) is sent buffered.
Timeouts
Connect (DNS + TCP + TLS)
30s → ERR_TIMED_OUT
TCP keepalive
60s on pooled connections
Whole request
uncapped — a streaming body may be long-lived by design
gzip, br, deflate — off the response's Content-Encoding
Stripped
Content-Encoding, Content-Length
Passed through
any other coding (zstd, …), headers intact
Requests carry User-Agent: ES-Runtime/<version> unless you set your own. Both are properties of the default transport.
Redirects
redirect
Behaviour
"follow" (default)
follows, cap 20; past it ERR_TOO_MANY_REDIRECTS
"manual"
resolves with the 3xx, Location intact
"error"
rejects with TypeError
JavaScript
const r = await fetch(url, { redirect: "manual" });
r.status; // 302
r.headers.get("location"); // where it would have gone
r.redirected; // false — nothing was followed
An unknown mode throws TypeError from new Request. Under "manual" the real response is returned, not the spec's opaque-redirect filtered one — same as Node, Deno and Bun.
Not available
Global
Why not
process / Buffer / require
Node.js globals — not provided (use runtime: modules)
SharedWorker
shares one worker between documents, and there are none
localStorage / window
browser globals — out of scope
navigator.* beyond userAgent and hardwareConcurrency
document/device/permission surface — out of scope; a plausible answer would make a feature check pass and lie