Implementation:Puppeteer Puppeteer HandleIterator
| Property | Value |
|---|---|
| sources | packages/puppeteer-core/src/common/HandleIterator.ts |
| domains | Handle Management, Iteration, Performance |
| last_updated | 2026-02-12 00:00 GMT |
Overview
Description
HandleIterator is an internal module that provides efficient transposition of iterator JSHandles from the browser context into Puppeteer-side (Node.js-side) JSHandle iterators. This is a critical performance optimization for operations like querySelectorAll that return multiple element handles from the browser.
The module contains three functions:
- fastTransposeIteratorHandle -- A private async generator that transposes a batch of elements from a browser-side iterator JSHandle into individual Puppeteer-side JSHandles. It evaluates the iterator in the browser to collect up to
sizeresults at once, then extracts each as a separate handle. It uses theusingkeyword withDisposableStackfor proper resource cleanup.
- transposeIteratorHandle -- A private async generator that wraps fastTransposeIteratorHandle with an exponential batch size strategy. It starts with a default batch size of 20 and doubles it on each iteration (using bit shifting:
size <<= 1), enabling efficient handling of both small and large result sets.
- transposeIterableHandle -- The public async generator that serves as the entry point. It converts a JSHandle to an
AwaitableIterableinto an async iterable of individual element handles by first wrapping the iterable in an async generator on the browser side, then delegating to transposeIteratorHandle.
Usage
This module is used internally by QueryHandler.queryAll and other internal methods that need to iterate over collections of elements returned from browser evaluations. It is not exposed in the public API.
Code Reference
Source Location
packages/puppeteer-core/src/common/HandleIterator.ts
Signature
const DEFAULT_BATCH_SIZE = 20;
async function* fastTransposeIteratorHandle<T>(
iterator: JSHandle<AwaitableIterator<T>>,
size: number,
): AsyncGenerator<HandleFor<T>, boolean>;
async function* transposeIteratorHandle<T>(
iterator: JSHandle<AwaitableIterator<T>>,
): AsyncGenerator<HandleFor<T>>;
export async function* transposeIterableHandle<T>(
handle: JSHandle<AwaitableIterable<T>>,
): AsyncIterableIterator<HandleFor<T>>;
Import
import {transposeIterableHandle} from './HandleIterator.js';
I/O Contract
| Parameter | Type | Description |
|---|---|---|
| handle | JSHandle<AwaitableIterable<T>> |
A JSHandle pointing to an iterable (sync or async) in the browser context |
| Return Type | Description |
|---|---|
AsyncIterableIterator<HandleFor<T>> |
An async iterable that yields individual JSHandle or ElementHandle instances for each element in the browser-side iterable |
Usage Examples
// Internal usage within QueryHandler.queryAll
import {transposeIterableHandle} from './HandleIterator.js';
// Given a JSHandle to an iterable of nodes in the browser:
const iterableHandle = await element.evaluateHandle(
querySelectorAll,
selector,
puppeteerUtil,
);
// Transpose it into individual Puppeteer-side handles
for await (const handle of transposeIterableHandle(iterableHandle)) {
// Each handle is an ElementHandle<Node> or JSHandle<T>
console.log(await handle.evaluate(el => el.textContent));
handle.dispose();
}