Implementation:Puppeteer Puppeteer Cdp LifecycleWatcher
| Property | Value |
|---|---|
| sources | packages/puppeteer-core/src/cdp/LifecycleWatcher.ts
|
| domains | CDP, Navigation, Lifecycle Events |
| last_updated | 2026-02-12 00:00 GMT |
Overview
Description
The LifecycleWatcher class monitors frame lifecycle events and navigation state to determine when a navigation has completed. It is the core mechanism behind page.goto(), page.waitForNavigation(), and similar navigation-awaiting methods in the CDP implementation.
The class subscribes to multiple event sources:
- FrameManager events --
LifecycleEventfor tracking page lifecycle milestones. - Frame events --
FrameNavigatedWithinDocument(same-document navigations like hash changes),FrameNavigated(full navigations),FrameSwappedandFrameSwappedByActivation(back-forward cache restores), andFrameDetached. - NetworkManager events --
Request,Response, andRequestFailedfor tracking the navigation request and its response.
The watcher maps Puppeteer lifecycle event names (load, domcontentloaded, networkidle0, networkidle2) to their CDP protocol equivalents (load, DOMContentLoaded, networkIdle, networkAlmostIdle).
The module also exports the PuppeteerLifeCycleEvent and ProtocolLifeCycleEvent type aliases.
Usage
LifecycleWatcher is created internally by the CDP frame manager during navigations. It resolves different deferred promises depending on the type of navigation completed (same-document, new-document, or lifecycle-only), and provides a termination promise that resolves on timeout or frame detachment.
Code Reference
Source Location
packages/puppeteer-core/src/cdp/LifecycleWatcher.ts (276 lines)
Signature
export type PuppeteerLifeCycleEvent =
| 'load'
| 'domcontentloaded'
| 'networkidle0'
| 'networkidle2';
export type ProtocolLifeCycleEvent =
| 'load'
| 'DOMContentLoaded'
| 'networkIdle'
| 'networkAlmostIdle';
export class LifecycleWatcher {
constructor(
networkManager: NetworkManager,
frame: CdpFrame,
waitUntil: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[],
timeout: number,
signal?: AbortSignal,
);
async navigationResponse(): Promise<HTTPResponse | null>;
sameDocumentNavigationPromise(): Promise<Error | undefined>;
newDocumentNavigationPromise(): Promise<Error | undefined>;
lifecyclePromise(): Promise<void>;
terminationPromise(): Promise<Error | TimeoutError | undefined>;
dispose(): void;
}
Import
import { LifecycleWatcher } from '../cdp/LifecycleWatcher.js';
import type { PuppeteerLifeCycleEvent, ProtocolLifeCycleEvent } from '../cdp/LifecycleWatcher.js';
I/O Contract
Constructor
| Direction | Name | Type | Description |
|---|---|---|---|
| Input | networkManager | NetworkManager |
The CDP network manager for tracking navigation requests |
| Input | frame | CdpFrame |
The frame being navigated |
| Input | waitUntil | PuppeteerLifeCycleEvent[] | Lifecycle event(s) to wait for (e.g., 'load', 'networkidle0')
|
| Input | timeout | number |
Navigation timeout in milliseconds |
| Input | signal | undefined | Optional abort signal to cancel the navigation wait |
Promise accessors
| Method | Return Type | Description |
|---|---|---|
navigationResponse() |
null> | The HTTP response for the navigation request |
sameDocumentNavigationPromise() |
undefined> | Resolves on same-document navigation (e.g., hash change) |
newDocumentNavigationPromise() |
undefined> | Resolves on new-document navigation (loader ID change or frame swap) |
lifecyclePromise() |
Promise<void> |
Resolves when all expected lifecycle events have fired |
terminationPromise() |
TimeoutError | undefined> | Resolves on timeout, frame detachment, or abort signal |
Usage Examples
import { LifecycleWatcher } from '../cdp/LifecycleWatcher.js';
// Internal usage within the frame manager for page.goto()
const watcher = new LifecycleWatcher(
networkManager,
frame,
'networkidle0',
30000, // 30 second timeout
);
// Race between lifecycle completion and termination
const result = await Promise.race([
watcher.lifecyclePromise(),
watcher.terminationPromise(),
watcher.newDocumentNavigationPromise(),
]);
// Get the navigation response
const response = await watcher.navigationResponse();
// Clean up subscriptions
watcher.dispose();