Event loop
The loop each thread runs: take one task, run it to completion, drain microtasks, maybe render, repeat.
in practiceWhy a long task freezes input and animation; why await does not block the thread.
How JavaScript runs on the page: the event loop, tasks and microtasks, long tasks and yielding, the engine's fast paths, memory and leaks, workers, and async.
How work is scheduled on the main thread and how the engine runs it fast.
The loop each thread runs: take one task, run it to completion, drain microtasks, maybe render, repeat.
in practiceWhy a long task freezes input and animation; why await does not block the thread.
A unit of work the event loop runs whole: a script, an event dispatch, a timer callback, a message.
in practiceThe grey "Task" bars in the Performance panel; setTimeout and MessageChannel schedule them.
A callback queued to run right after the current task and before rendering: promise reactions, queueMicrotask, MutationObserver.
in practicePromise chains that starve rendering if they keep queuing more microtasks.
Any task over 50 ms; while it runs, input waits and frames are not produced.
in practiceRed-cornered tasks in the Performance panel; the main driver of INP and Total Blocking Time.
Breaking work into chunks and returning to the event loop between them so input and rendering can run.
in practicescheduler.yield(), await on a setTimeout(0), chunked loops; the main fix for long tasks.
A prioritised task scheduler (user-blocking, user-visible, background) with abort signals, plus scheduler.yield() to continue at the same priority.
in practiceDeferring analytics and prefetch to background priority behind user work.
Runs a callback when the browser is idle in a frame, with a deadline telling it how much time is left.
in practiceLow-priority work like sending telemetry or warming caches.
The stack of function frames currently executing; the event loop only takes the next task when it is empty.
in practiceStack traces in errors; "Maximum call stack size exceeded" from unbounded recursion.
The record of variables, this and the outer scope for a running function; closures keep an outer scope alive after it returns.
in practiceClosures over stale state in React effects; memory held by a closure you forgot.
A per-call-site cache of the shapes seen and where the property lives, turning a lookup into an offset read.
in practiceMonomorphic call sites (one shape) are fast; megamorphic ones (many) fall back to slow lookups.
Compiling hot functions to machine code using type feedback, and deoptimising when an assumption breaks.
in practiceCode fast after warm-up and slower when types change; --trace-deopt.
What stays in memory, what runs elsewhere, and how asynchronous work is expressed and cancelled.
Automatic reclamation of objects no longer reachable from roots; V8 uses a fast young-generation scavenger and a mostly concurrent old-generation mark-compact.
in practiceGC slices in traces; pauses on allocation-heavy code; memory that does not drop because something still references it.
Memory that stays reachable when the app no longer needs it: detached DOM, forgotten listeners, growing caches, closures held by timers.
in practiceThe Memory panel's heap snapshots and comparison view; a tab that slows down over an hour.
DOM nodes removed from the document but still referenced by JS, so they and their subtrees cannot be collected.
in practiceSearch "Detached" in a heap snapshot; a modal's nodes held by a closure after close.
References that do not keep their target alive: WeakMap keys and WeakRef targets can be collected when nothing else holds them.
in practiceCaches keyed by DOM nodes or objects without leaking them.
A separate thread with its own event loop and no DOM, communicating with the page by messages.
in practiceMoving parsing, search indexing, image processing and CRDT merges off the main thread.
How postMessage copies data between threads (structured clone) or moves ownership of buffers with zero copy (transferables).
in practiceLarge ArrayBuffers transferred, not copied; functions and DOM nodes cannot be cloned.
Memory shared between threads with atomic operations for coordination; requires cross-origin isolation.
in practiceWASM threads, high-performance pipelines; COOP and COEP headers to enable it.
A worker that sits between the page and the network for its scope, intercepting fetches, caching, and receiving push.
in practiceOffline apps, cache strategies, the Application panel's Service Workers pane; stale app bugs after deploys.
An object representing a future value, settled once as fulfilled or rejected, with reactions queued as microtasks.
in practiceasync/await is promise sugar; unhandled rejections; Promise.all versus allSettled.
Syntax that suspends a function at each await and resumes it as a microtask when the promise settles, without blocking the thread.
in practiceSequential awaits that should be parallel (Promise.all); try/catch for rejections.
A signal that cancels fetches, listeners and any API that accepts it, so stale work stops instead of racing.
in practiceCancelling the previous search request on each keystroke; cleanup in React effects.
Events travel capture (window down to target), target, then bubble (back up); listeners can stop it or prevent the default action.
in practiceEvent delegation on a list; stopPropagation breaking analytics; passive listeners for scroll and touch.