Implementation:Puppeteer Puppeteer Cdp ExecutionContext
| Property | Value |
|---|---|
| sources | packages/puppeteer-core/src/cdp/ExecutionContext.ts |
| domains | JavaScript Execution, CDP, Browser Automation |
| last_updated | 2026-02-12 00:00 GMT |
Overview
Description
The ExecutionContext class represents a JavaScript execution context within the browser. Each frame has at least one execution context (the main world), and Puppeteer creates an additional isolated context (the Puppeteer world) for internal operations. The class provides the core mechanism for evaluating JavaScript expressions and functions in the browser.
Key responsibilities include:
- JavaScript evaluation -- Executing functions or string expressions in the browser context via
Runtime.evaluate(for strings) andRuntime.callFunctionOn(for functions), with support for returning values by value or as handles. - Argument serialization -- Converting JavaScript values, JSHandles, and ElementHandles into CDP
CallArgumentobjects. Handles special values likebigint,-0,Infinity,-Infinity, andNaN. - Binding management -- Installing CDP runtime bindings (
Runtime.addBinding) that allow page-side JavaScript to call Puppeteer-side functions. Uses aMutexto prevent race conditions during async binding setup. Manages ARIA query selector bindings for accessibility queries. - Event forwarding -- Listening for
Runtime.consoleAPICalledandRuntime.bindingCalledevents and forwarding them as typed events. - Lifecycle management -- Implementing
Disposableto clean up when the execution context is destroyed (navigation, context clearing, or disconnection). Listens forRuntime.executionContextDestroyedandRuntime.executionContextsClearedevents. - Puppeteer utility injection -- Lazily injecting the
PuppeteerInjectedUtilscript into the context for internal query and DOM operations.
Error handling includes rewriting CDP errors for common cases like "Object reference chain is too long" and "Object couldn't be returned by value."
Usage
ExecutionContext instances are created internally by the FrameManager when new execution contexts are reported by CDP. Users typically interact indirectly through frame.evaluate(), frame.evaluateHandle(), and similar methods.
Code Reference
Source Location: packages/puppeteer-core/src/cdp/ExecutionContext.ts (549 lines)
Signature:
export class ExecutionContext
extends EventEmitter<{
disposed: undefined;
consoleapicalled: Protocol.Runtime.ConsoleAPICalledEvent;
bindingcalled: Protocol.Runtime.BindingCalledEvent;
}>
implements Disposable
{
constructor(
client: CDPSession,
contextPayload: Protocol.Runtime.ExecutionContextDescription,
world: IsolatedWorld,
);
get id(): number;
async evaluate<Params extends unknown[], Func extends EvaluateFunc<Params>>(
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async evaluateHandle<Params extends unknown[], Func extends EvaluateFunc<Params>>(
pageFunction: Func | string,
...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
get puppeteerUtil(): Promise<JSHandle<PuppeteerInjectedUtil>>;
}
Import:
import { ExecutionContext } from 'puppeteer-core/lib/cdp/ExecutionContext.js';
I/O Contract
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
| client | CDPSession |
Yes | The CDP session for sending commands |
| contextPayload | Protocol.Runtime.ExecutionContextDescription |
Yes | The CDP execution context descriptor (id, name, auxData) |
| world | IsolatedWorld |
Yes | The isolated world this context belongs to |
| pageFunction | string | Yes | The function or expression to evaluate |
| args | unknown[] |
No | Arguments to pass to the function (supports JSHandle, ElementHandle, bigint, special numeric values) |
Outputs:
| Output | Type | Description |
|---|---|---|
| evaluate() return | Promise<T> |
The serialized return value of the evaluated function |
| evaluateHandle() return | ElementHandle> | A handle to the in-browser object (JSHandle for non-elements, ElementHandle for DOM nodes) |
| id | number |
The CDP execution context ID |
Usage Examples
// Evaluate a simple expression
const result = await page.evaluate(() => Promise.resolve(8 * 7));
console.log(result); // 56
// Evaluate a string expression
console.log(await page.evaluate('1 + 2')); // 3
// Evaluate with arguments (handles resolve to their referenced objects)
const oneHandle = await page.evaluateHandle(() => 1);
const twoHandle = await page.evaluateHandle(() => 2);
const result = await page.evaluate(
(a, b) => a + b,
oneHandle,
twoHandle,
);
await oneHandle.dispose();
await twoHandle.dispose();
console.log(result); // 3
// Get a handle to a DOM element
const bodyHandle = await page.evaluateHandle(() => document.body);
const html = await page.evaluate(body => body.innerHTML, bodyHandle);
await bodyHandle.dispose();
// Get a handle to a complex object (Map, Set, etc.)
const mapHandle = await page.evaluateHandle(() => new Map([['key', 'value']]));