Implementation:Puppeteer Puppeteer Bidi Frame
| Property | Value |
|---|---|
| Implementation | BidiFrame |
| Source File | packages/puppeteer-core/src/bidi/Frame.ts
|
| Repository | puppeteer/puppeteer |
| Lines | 669 |
| License | Apache-2.0 |
| Copyright | 2023 Google Inc. |
Overview
Description
BidiFrame is the WebDriver BiDi implementation of the Puppeteer Frame abstract class. It represents a browser frame (the main frame or an iframe) and provides methods for navigating, evaluating JavaScript, interacting with page content, and managing child frames. The class bridges the high-level Puppeteer Frame API with the low-level BiDi BrowsingContext protocol layer.
BidiFrame is constructed via its static from() factory method and maintains two realms: a default realm for user-facing script evaluation and an internal realm (a sandboxed window realm) used by Puppeteer's internal utilities. It listens on its underlying BrowsingContext for events such as navigation, requests, console logs, dialogs, worker creation, and lifecycle events (load, DOMContentLoaded), and re-emits them as Puppeteer PageEvent emissions on the parent page.
Key responsibilities include:
- Navigation:
goto(),waitForNavigation(),setContent()with support for wait conditions (load,domcontentloaded,networkidle0,networkidle2). - Frame hierarchy: Managing child frames through
childFrames(),parentFrame(), and automatic creation/teardown on browsing context events. - Request lifecycle: Creating
BidiHTTPRequestobjects for each network request and emitting request finished/failed events. - Console and error handling: Translating BiDi log entries into Puppeteer
ConsoleMessageandPageErrorevents. - Exposed functions:
exposeFunction()andremoveExposedFunction()for injecting JavaScript bindings. - CDP session creation:
createCDPSession()for fallback to Chrome DevTools Protocol when supported.
Usage
BidiFrame instances are not created directly by users. They are created internally when a BidiPage is constructed or when child browsing contexts appear. Users interact with frames through the Page.mainFrame() and Page.frames() APIs.
Code Reference
Source Location
packages/puppeteer-core/src/bidi/Frame.ts (GitHub)
Signature
export class BidiFrame extends Frame {
static from(
parent: BidiPage | BidiFrame,
browsingContext: BrowsingContext,
): BidiFrame;
readonly browsingContext: BrowsingContext;
readonly realms: {default: BidiFrameRealm; internal: BidiFrameRealm};
override readonly _id: string;
override readonly client: BidiCdpSession;
override readonly accessibility: Accessibility;
override mainRealm(): BidiFrameRealm;
override isolatedRealm(): BidiFrameRealm;
realm(id: string): BidiRealm | undefined;
override page(): BidiPage;
override url(): string;
override parentFrame(): BidiFrame | null;
override childFrames(): BidiFrame[];
override async goto(url: string, options?: GoToOptions): Promise<BidiHTTPResponse | null>;
override async setContent(html: string, options?: WaitForOptions): Promise<void>;
override async waitForNavigation(options?: WaitForOptions): Promise<BidiHTTPResponse | null>;
override waitForDevicePrompt(options?: WaitTimeoutOptions): Promise<DeviceRequestPrompt>;
override get detached(): boolean;
async exposeFunction<Args extends unknown[], Ret>(
name: string, apply: (...args: Args) => Awaitable<Ret>
): Promise<void>;
async removeExposedFunction(name: string): Promise<void>;
async createCDPSession(): Promise<CDPSession>;
async setFiles(element: BidiElementHandle, files: string[]): Promise<void>;
override async frameElement(): Promise<HandleFor<HTMLIFrameElement> | null>;
async locateNodes(
element: BidiElementHandle, locator: Bidi.BrowsingContext.Locator
): Promise<Bidi.Script.NodeRemoteValue[]>;
}
Import
import {BidiFrame} from './Frame.js';
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
| parent | BidiFrame | The parent page or frame that owns this frame |
| browsingContext | BrowsingContext |
The low-level BiDi browsing context this frame wraps |
Key Method Parameters
| Method | Parameter | Type | Description |
|---|---|---|---|
| goto | url | string |
The URL to navigate to |
| goto | options | GoToOptions |
Navigation options including timeout, waitUntil, referer |
| waitForNavigation | options | WaitForOptions |
Options controlling wait conditions: waitUntil (load, domcontentloaded, networkidle0, networkidle2), timeout |
| setContent | html | string |
HTML content to set on the frame |
| exposeFunction | name | string |
Name of the function to expose on globalThis |
| exposeFunction | apply | (...args) => Awaitable<Ret> |
The function implementation |
Outputs
| Method | Return Type | Description |
|---|---|---|
| goto | null> | The HTTP response of the navigation, or null |
| waitForNavigation | null> | The response after navigation completes |
| url | string |
The current URL of the frame |
| childFrames | BidiFrame[] |
Array of child frames |
| parentFrame | null | The parent frame, or null if this is the main frame |
| page | BidiPage |
The page that owns this frame |
| detached | boolean |
Whether the frame has been detached from the DOM |
Usage Examples
// Navigate the main frame to a URL
const page = await browser.newPage();
const response = await page.mainFrame().goto('https://example.com', {
waitUntil: 'networkidle0',
timeout: 30000,
});
// Wait for navigation triggered by a click
const [navResponse] = await Promise.all([
page.mainFrame().waitForNavigation({waitUntil: 'domcontentloaded'}),
page.click('a#my-link'),
]);
// Set HTML content on the frame
await page.mainFrame().setContent('<h1>Hello World</h1>', {
waitUntil: 'load',
});
// Expose a function to the page
await page.mainFrame().exposeFunction('myFunc', (a: number, b: number) => {
return a + b;
});
// Access child frames
const frames = page.mainFrame().childFrames();
for (const frame of frames) {
console.log(frame.url());
}
// Check if frame is detached
if (!page.mainFrame().detached) {
await page.mainFrame().goto('https://example.com/next');
}