feat: export public types only (#8584)

This commit is contained in:
jrandolf 2022-06-27 09:24:23 +02:00 committed by GitHub
parent 9787a1d8df
commit 7001322cd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 537 additions and 501 deletions

View File

@ -5,4 +5,4 @@ doclint/
lib/ lib/
test-ts-types/ test-ts-types/
tsconfig.tsbuildinfo tsconfig.tsbuildinfo
vendor/ vendor/

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ docs/api.html
lib/ lib/
node_modules/ node_modules/
package-lock.json package-lock.json
puppeteer.api.json
puppeteer*.tgz puppeteer*.tgz
test-ts-types/**/dist/ test-ts-types/**/dist/
test-ts-types/**/node_modules test-ts-types/**/node_modules

View File

@ -5,7 +5,6 @@ build/
CHANGELOG.md CHANGELOG.md
coverage/ coverage/
doclint/ doclint/
docs-api-json/
lib/ lib/
node_modules/ node_modules/
package-lock.json package-lock.json
@ -14,4 +13,5 @@ test-ts-types/
test/assets/ test/assets/
tsconfig.tsbuildinfo tsconfig.tsbuildinfo
vendor/ vendor/
yarn.lock yarn.lock
puppeteer.api.json

View File

@ -1,6 +1,6 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "<projectFolder>/lib/cjs/puppeteer/api-docs-entry.d.ts", "mainEntryPointFilePath": "<projectFolder>/lib/esm/puppeteer/types.d.ts",
"bundledPackages": [], "bundledPackages": [],
"apiReport": { "apiReport": {
@ -9,12 +9,13 @@
"docModel": { "docModel": {
"enabled": true, "enabled": true,
"apiJsonFilePath": "<projectFolder>/docs-api-json/<unscopedPackageName>.api.json" "apiJsonFilePath": "<projectFolder>/docs/<unscopedPackageName>.api.json"
}, },
"dtsRollup": { "dtsRollup": {
"enabled": true, "enabled": true,
"untrimmedFilePath": "lib/types.d.ts" "untrimmedFilePath": "",
"alphaTrimmedFilePath": "lib/types.d.ts"
}, },
"tsdocMetadata": { "tsdocMetadata": {

View File

@ -1,5 +1,8 @@
import {dirname} from 'path'; import {dirname} from 'path';
/**
* @internal
*/
let puppeteerDirname: string; let puppeteerDirname: string;
try { try {

View File

@ -4,6 +4,9 @@ import {fileURLToPath} from 'url';
const require = createRequire(import.meta.url); const require = createRequire(import.meta.url);
/**
* @internal
*/
let puppeteerDirname: string; let puppeteerDirname: string;
try { try {

View File

@ -44,7 +44,7 @@
"lint:eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)", "lint:eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)",
"lint:eslint:fix": "eslint --ext js --ext ts --fix .", "lint:eslint:fix": "eslint --ext js --ext ts --fix .",
"install": "node install.js", "install": "node install.js",
"generate:types": "npm run clean:docs && api-extractor run --local --verbose", "generate:types": "node utils/export_all.js && api-extractor run --local --verbose",
"generate:esm-package-json": "echo '{\"type\": \"module\"}' > lib/esm/package.json", "generate:esm-package-json": "echo '{\"type\": \"module\"}' > lib/esm/package.json",
"generate:docs": "npm run generate:types && node utils/remove-tag.js", "generate:docs": "npm run generate:types && node utils/remove-tag.js",
"generate:docs:testing": "commonmark docs/api.md > docs/api.html", "generate:docs:testing": "commonmark docs/api.md > docs/api.html",
@ -52,7 +52,6 @@
"doc": "node utils/doclint/cli.js", "doc": "node utils/doclint/cli.js",
"commitlint": "commitlint --from=HEAD~1", "commitlint": "commitlint --from=HEAD~1",
"clean:lib": "rimraf lib", "clean:lib": "rimraf lib",
"clean:docs": "rimraf docs-api-json",
"build": "npm run build:tsc && npm run generate:types && npm run generate:esm-package-json", "build": "npm run build:tsc && npm run generate:types && npm run generate:esm-package-json",
"build:test": "tsc -b test", "build:test": "tsc -b test",
"build:tsc": "npm run clean:lib && tsc --version && (npm run build:tsc:cjs && npm run build:tsc:esm)", "build:tsc": "npm run clean:lib && tsc --version && (npm run build:tsc:cjs && npm run build:tsc:esm)",

View File

@ -1,152 +0,0 @@
/**
* Copyright 2020 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
LaunchOptions,
BrowserLaunchArgumentOptions,
} from './node/LaunchOptions.js';
import {BrowserConnectOptions} from './common/BrowserConnector.js';
import {Product} from './common/Product.js';
import {Browser} from './common/Browser.js';
import {ConnectOptions} from './common/Puppeteer.js';
import {DevicesMap} from './common/DeviceDescriptors.js';
import {PuppeteerErrors} from './common/Errors.js';
import {PredefinedNetworkConditions} from './common/NetworkConditions.js';
import {CustomQueryHandler} from './common/QueryHandler.js';
/*
* This file re-exports any APIs that we want to have documentation generated
* for. It is used by API Extractor to determine what parts of the system to
* document.
*
* The legacy DocLint system and the unit test coverage system use the list of
* modules defined in coverage-utils.js. src/api-docs-entry.ts is ONLY used by
* API Extractor.
*
* Once we have migrated to API Extractor and removed DocLint we can remove the
* duplication and use this file.
*/
export * from './common/Accessibility.js';
export * from './common/Browser.js';
export * from './common/BrowserConnector.js';
export * from './common/Connection.js';
export * from './common/ConsoleMessage.js';
export * from './common/Coverage.js';
export * from './common/Coverage.js';
export * from './common/DeviceDescriptors.js';
export * from './common/Dialog.js';
export * from './common/DOMWorld.js';
export * from './common/ElementHandle.js';
export * from './common/Errors.js';
export * from './common/EventEmitter.js';
export * from './common/ExecutionContext.js';
export * from './common/FileChooser.js';
export * from './common/FrameManager.js';
export * from './common/HTTPRequest.js';
export * from './common/HTTPResponse.js';
export * from './common/Input.js';
export * from './common/JSHandle.js';
export * from './common/LifecycleWatcher.js';
export * from './common/NetworkConditions.js';
export * from './common/NetworkManager.js';
export * from './common/Page.js';
export * from './common/PDFOptions.js';
export * from './common/Product.js';
export * from './common/Puppeteer.js';
export * from './common/PuppeteerViewport.js';
export * from './common/QueryHandler.js';
export * from './common/SecurityDetails.js';
export * from './common/Target.js';
export * from './common/TimeoutSettings.js';
export * from './common/Tracing.js';
export * from './common/types.js';
export * from './common/USKeyboardLayout.js';
export * from './common/WebWorker.js';
export * from './node/BrowserFetcher.js';
export * from './node/LaunchOptions.js';
export * from './node/ProductLauncher.js';
export * from './node/Puppeteer.js';
export * from 'devtools-protocol/types/protocol';
/*
* We maintain a namespace that emulates the API of the Puppeteer instance you
* get when you `import puppeteer from 'puppeteer'.
*
* We do this as a namespace because export = PuppeteerDefault where
* PuppeteerDefault is a namespace seems to make sure that the types work in
* both ESM and CJS contexts.
*
* This namespace must be kept in sync with the public API offered by the
* PuppeteerNode class.
*/
/**
* @public
* {@inheritDoc PuppeteerNode.launch}
*/
export declare function launch(
options?: LaunchOptions &
BrowserLaunchArgumentOptions &
BrowserConnectOptions & {
product?: Product;
extraPrefsFirefox?: Record<string, unknown>;
}
): Promise<Browser>;
/**
* @public
* {@inheritDoc PuppeteerNode.connect}
*/
export declare function connect(options: ConnectOptions): Promise<Browser>;
/**
* @public
* {@inheritDoc Puppeteer.devices}
*/
export let devices: DevicesMap;
/**
* @public
*/
export let errors: PuppeteerErrors;
/**
* @public
*/
export let networkConditions: PredefinedNetworkConditions;
/**
* @public
* {@inheritDoc Puppeteer.registerCustomQueryHandler}
*/
export declare function registerCustomQueryHandler(
name: string,
queryHandler: CustomQueryHandler
): void;
/**
* @public
* {@inheritDoc Puppeteer.unregisterCustomQueryHandler}
*/
export declare function unregisterCustomQueryHandler(name: string): void;
/**
* @public
* {@inheritDoc Puppeteer.customQueryHandlerNames}
*/
export declare function customQueryHandlerNames(): string[];
/**
* @public
* {@inheritDoc Puppeteer.clearCustomQueryHandlers}
*/
export declare function clearCustomQueryHandlers(): void;

View File

@ -15,6 +15,9 @@
*/ */
import {ConnectionTransport} from './ConnectionTransport.js'; import {ConnectionTransport} from './ConnectionTransport.js';
/**
* @internal
*/
export class BrowserWebSocketTransport implements ConnectionTransport { export class BrowserWebSocketTransport implements ConnectionTransport {
static create(url: string): Promise<BrowserWebSocketTransport> { static create(url: string): Promise<BrowserWebSocketTransport> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -24,7 +24,7 @@ import {Frame, FrameManager} from './FrameManager.js';
import {MouseButton} from './Input.js'; import {MouseButton} from './Input.js';
import {JSHandle} from './JSHandle.js'; import {JSHandle} from './JSHandle.js';
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {_getQueryHandlerAndSelector} from './QueryHandler.js'; import {getQueryHandlerAndSelector} from './QueryHandler.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {EvaluateFunc, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import { import {
@ -653,7 +653,7 @@ export class DOMWorld {
options: WaitForSelectorOptions options: WaitForSelectorOptions
): Promise<ElementHandle | null> { ): Promise<ElementHandle | null> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
_getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert(queryHandler.waitFor, 'Query handler does not support waiting'); assert(queryHandler.waitFor, 'Query handler does not support waiting');
return queryHandler.waitFor(this, updatedSelector, options); return queryHandler.waitFor(this, updatedSelector, options);
} }

View File

@ -25,14 +25,10 @@ declare global {
* A debug function that can be used in any environment. * A debug function that can be used in any environment.
* *
* @remarks * @remarks
*
* If used in Node, it falls back to the * If used in Node, it falls back to the
* {@link https://www.npmjs.com/package/debug | debug module}. In the browser it * {@link https://www.npmjs.com/package/debug | debug module}. In the browser it
* uses `console.log`. * uses `console.log`.
* *
* @param prefix - this will be prefixed to each log.
* @returns a function that can be called to log to that debug channel.
*
* In Node, use the `DEBUG` environment variable to control logging: * In Node, use the `DEBUG` environment variable to control logging:
* *
* ``` * ```
@ -56,6 +52,11 @@ declare global {
* log('new page created') * log('new page created')
* // logs "Page: new page created" * // logs "Page: new page created"
* ``` * ```
*
* @param prefix - this will be prefixed to each log.
* @returns a function that can be called to log to that debug channel.
*
* @internal
*/ */
export const debug = (prefix: string): ((...args: unknown[]) => void) => { export const debug = (prefix: string): ((...args: unknown[]) => void) => {
if (isNode) { if (isNode) {

View File

@ -30,7 +30,7 @@ export interface Device {
}; };
} }
const devices: Device[] = [ const deviceArray: Device[] = [
{ {
name: 'Blackberry PlayBook', name: 'Blackberry PlayBook',
userAgent: userAgent:
@ -1536,10 +1536,30 @@ export type DevicesMap = {
}; };
/** /**
* @internal * A list of devices to be used with `page.emulate(options)`. Actual list of devices can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts | src/common/DeviceDescriptors.ts}.
*
* @example
*
* ```js
* const puppeteer = require('puppeteer');
* const iPhone = puppeteer.devices['iPhone 6'];
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.emulate(iPhone);
* await page.goto('https://www.google.com');
* // other actions...
* await browser.close();
* })();
* ```
*
* @public
*/ */
export const _devicesMap: DevicesMap = {}; const devices: DevicesMap = {};
for (const device of devices) { for (const device of deviceArray) {
_devicesMap[device.name] = device; devices[device.name] = device;
} }
export {devices};

View File

@ -8,14 +8,13 @@ import {
BoundingBox, BoundingBox,
BoxModel, BoxModel,
ClickOptions, ClickOptions,
computeQuadArea,
JSHandle, JSHandle,
Offset, Offset,
Point, Point,
PressOptions, PressOptions,
} from './JSHandle.js'; } from './JSHandle.js';
import {Page, ScreenshotOptions} from './Page.js'; import {Page, ScreenshotOptions} from './Page.js';
import {_getQueryHandlerAndSelector} from './QueryHandler.js'; import {getQueryHandlerAndSelector} from './QueryHandler.js';
import {EvaluateFunc} from './types.js'; import {EvaluateFunc} from './types.js';
import {KeyInput} from './USKeyboardLayout.js'; import {KeyInput} from './USKeyboardLayout.js';
import {debugError, isString} from './util.js'; import {debugError, isString} from './util.js';
@ -841,7 +840,7 @@ export class ElementHandle<
async $(selector: string): Promise<ElementHandle | null>; async $(selector: string): Promise<ElementHandle | null>;
async $(selector: string): Promise<ElementHandle | null> { async $(selector: string): Promise<ElementHandle | null> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
_getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert( assert(
queryHandler.queryOne, queryHandler.queryOne,
'Cannot handle queries for a single element with the given selector' 'Cannot handle queries for a single element with the given selector'
@ -866,7 +865,7 @@ export class ElementHandle<
async $$(selector: string): Promise<ElementHandle[]>; async $$(selector: string): Promise<ElementHandle[]>;
async $$(selector: string): Promise<ElementHandle[]> { async $$(selector: string): Promise<ElementHandle[]> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
_getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert( assert(
queryHandler.queryAll, queryHandler.queryAll,
'Cannot handle queries for a multiple element with the given selector' 'Cannot handle queries for a multiple element with the given selector'
@ -986,7 +985,7 @@ export class ElementHandle<
...args: Params ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
_getQueryHandlerAndSelector(selector); getQueryHandlerAndSelector(selector);
assert(queryHandler.queryAllArray); assert(queryHandler.queryAllArray);
const arrayHandle = await queryHandler.queryAllArray(this, updatedSelector); const arrayHandle = await queryHandler.queryAllArray(this, updatedSelector);
const result = await arrayHandle.evaluate(pageFunction, ...args); const result = await arrayHandle.evaluate(pageFunction, ...args);
@ -1046,3 +1045,16 @@ export class ElementHandle<
}, threshold); }, threshold);
} }
} }
function computeQuadArea(quad: Point[]): number {
/* Compute sum of all directed areas of adjacent triangles
https://en.wikipedia.org/wiki/Polygon#Simple_polygons
*/
let area = 0;
for (let i = 0; i < quad.length; ++i) {
const p1 = quad[i]!;
const p2 = quad[(i + 1) % quad.length]!;
area += (p1.x * p2.y - p2.x * p1.y) / 2;
}
return Math.abs(area);
}

View File

@ -17,6 +17,9 @@ import {CDPSession} from './Connection.js';
import {Viewport} from './PuppeteerViewport.js'; import {Viewport} from './PuppeteerViewport.js';
import {Protocol} from 'devtools-protocol'; import {Protocol} from 'devtools-protocol';
/**
* @internal
*/
export class EmulationManager { export class EmulationManager {
#client: CDPSession; #client: CDPSession;
#emulatingMobile = false; #emulatingMobile = false;

View File

@ -26,12 +26,12 @@ export class CustomError extends Error {
} }
/** /**
* TimeoutError is emitted whenever certain operations are terminated due to timeout. * TimeoutError is emitted whenever certain operations are terminated due to
* timeout.
* *
* @remarks * @remarks
* * Example operations are {@link Page.waitForSelector | page.waitForSelector} or
* Example operations are {@link Page.waitForSelector | page.waitForSelector} * {@link PuppeteerNode.launch | puppeteer.launch}.
* or {@link PuppeteerNode.launch | puppeteer.launch}.
* *
* @public * @public
*/ */
@ -56,9 +56,28 @@ export interface PuppeteerErrors {
} }
/** /**
* Puppeteer methods might throw errors if they are unable to fulfill a request.
* For example, `page.waitForSelector(selector[, options])` might fail if the
* selector doesn't match any nodes during the given timeframe.
*
* For certain types of errors Puppeteer uses specific error classes. These
* classes are available via `puppeteer.errors`.
*
* @example
* An example of handling a timeout error:
* ```js
* try {
* await page.waitForSelector('.foo');
* } catch (e) {
* if (e instanceof puppeteer.errors.TimeoutError) {
* // Do something if this is a timeout.
* }
* }
* ```
*
* @public * @public
*/ */
export const puppeteerErrors: PuppeteerErrors = Object.freeze({ export const errors: PuppeteerErrors = Object.freeze({
TimeoutError, TimeoutError,
ProtocolError, ProtocolError,
}); });

View File

@ -1,97 +0,0 @@
/**
* Copyright 2019 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* IMPORTANT: we are mid-way through migrating away from this Events.ts file
* in favour of defining events next to the class that emits them.
*
* However we need to maintain this file for now because the legacy DocLint
* system relies on them. Be aware in the mean time if you make a change here
* you probably need to replicate it in the relevant class. For example if you
* add a new Page event, you should update the PageEmittedEvents enum in
* src/common/Page.ts.
*
* Chat to \@jackfranklin if you're unsure.
*/
export const Events = {
Page: {
Close: 'close',
Console: 'console',
Dialog: 'dialog',
DOMContentLoaded: 'domcontentloaded',
Error: 'error',
// Can't use just 'error' due to node.js special treatment of error events.
// @see https://nodejs.org/api/events.html#events_error_events
PageError: 'pageerror',
Request: 'request',
Response: 'response',
RequestFailed: 'requestfailed',
RequestFinished: 'requestfinished',
FrameAttached: 'frameattached',
FrameDetached: 'framedetached',
FrameNavigated: 'framenavigated',
Load: 'load',
Metrics: 'metrics',
Popup: 'popup',
WorkerCreated: 'workercreated',
WorkerDestroyed: 'workerdestroyed',
},
Browser: {
TargetCreated: 'targetcreated',
TargetDestroyed: 'targetdestroyed',
TargetChanged: 'targetchanged',
Disconnected: 'disconnected',
},
BrowserContext: {
TargetCreated: 'targetcreated',
TargetDestroyed: 'targetdestroyed',
TargetChanged: 'targetchanged',
},
NetworkManager: {
Request: Symbol('Events.NetworkManager.Request'),
Response: Symbol('Events.NetworkManager.Response'),
RequestFailed: Symbol('Events.NetworkManager.RequestFailed'),
RequestFinished: Symbol('Events.NetworkManager.RequestFinished'),
},
FrameManager: {
FrameAttached: Symbol('Events.FrameManager.FrameAttached'),
FrameNavigated: Symbol('Events.FrameManager.FrameNavigated'),
FrameDetached: Symbol('Events.FrameManager.FrameDetached'),
LifecycleEvent: Symbol('Events.FrameManager.LifecycleEvent'),
FrameNavigatedWithinDocument: Symbol(
'Events.FrameManager.FrameNavigatedWithinDocument'
),
ExecutionContextCreated: Symbol(
'Events.FrameManager.ExecutionContextCreated'
),
ExecutionContextDestroyed: Symbol(
'Events.FrameManager.ExecutionContextDestroyed'
),
},
Connection: {
Disconnected: Symbol('Events.Connection.Disconnected'),
},
CDPSession: {
Disconnected: Symbol('Events.CDPSession.Disconnected'),
},
} as const;

View File

@ -26,7 +26,7 @@ import {
getExceptionMessage, getExceptionMessage,
isString, isString,
valueFromRemoteObject, valueFromRemoteObject,
_createJSHandle, createJSHandle,
} from './util.js'; } from './util.js';
/** /**
@ -253,7 +253,7 @@ export class ExecutionContext {
return returnByValue return returnByValue
? valueFromRemoteObject(remoteObject) ? valueFromRemoteObject(remoteObject)
: _createJSHandle(this, remoteObject); : createJSHandle(this, remoteObject);
} }
if (typeof pageFunction !== 'function') { if (typeof pageFunction !== 'function') {
@ -309,7 +309,7 @@ export class ExecutionContext {
} }
return returnByValue return returnByValue
? valueFromRemoteObject(remoteObject) ? valueFromRemoteObject(remoteObject)
: _createJSHandle(this, remoteObject); : createJSHandle(this, remoteObject);
function convertArgument( function convertArgument(
this: ExecutionContext, this: ExecutionContext,
@ -407,7 +407,7 @@ export class ExecutionContext {
const response = await this._client.send('Runtime.queryObjects', { const response = await this._client.send('Runtime.queryObjects', {
prototypeObjectId: prototypeHandle._remoteObject.objectId, prototypeObjectId: prototypeHandle._remoteObject.objectId,
}); });
return _createJSHandle(this, response.objects) as HandleFor<Prototype[]>; return createJSHandle(this, response.objects) as HandleFor<Prototype[]>;
} }
/** /**
@ -420,7 +420,7 @@ export class ExecutionContext {
backendNodeId: backendNodeId, backendNodeId: backendNodeId,
executionContextId: this._contextId, executionContextId: this._contextId,
}); });
return _createJSHandle(this, object) as ElementHandle; return createJSHandle(this, object) as ElementHandle;
} }
/** /**

View File

@ -20,7 +20,7 @@ import {CDPSession} from './Connection.js';
import {EvaluateFunc, HandleFor, HandleOr} from './types.js'; import {EvaluateFunc, HandleFor, HandleOr} from './types.js';
import {ExecutionContext} from './ExecutionContext.js'; import {ExecutionContext} from './ExecutionContext.js';
import {MouseButton} from './Input.js'; import {MouseButton} from './Input.js';
import {releaseObject, valueFromRemoteObject, _createJSHandle} from './util.js'; import {releaseObject, valueFromRemoteObject, createJSHandle} from './util.js';
import type {ElementHandle} from './ElementHandle.js'; import type {ElementHandle} from './ElementHandle.js';
/** /**
@ -222,7 +222,7 @@ export class JSHandle<T = unknown> {
if (!property.enumerable || !property.value) { if (!property.enumerable || !property.value) {
continue; continue;
} }
result.set(property.name, _createJSHandle(this.#context, property.value)); result.set(property.name, createJSHandle(this.#context, property.value));
} }
return result; return result;
} }
@ -345,16 +345,3 @@ export interface Point {
x: number; x: number;
y: number; y: number;
} }
export function computeQuadArea(quad: Point[]): number {
/* Compute sum of all directed areas of adjacent triangles
https://en.wikipedia.org/wiki/Polygon#Simple_polygons
*/
let area = 0;
for (let i = 0; i < quad.length; ++i) {
const p1 = quad[i]!;
const p2 = quad[(i + 1) % quad.length]!;
area += (p1.x * p2.y - p2.x * p1.y) / 2;
}
return Math.abs(area);
}

View File

@ -17,14 +17,33 @@
import {NetworkConditions} from './NetworkManager.js'; import {NetworkConditions} from './NetworkManager.js';
/** /**
* A list of network conditions to be used with
* `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined
* conditions can be found in
* {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}.
*
* @example
*
* ```js
* const puppeteer = require('puppeteer');
* const slow3G = puppeteer.networkConditions['Slow 3G'];
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.emulateNetworkConditions(slow3G);
* await page.goto('https://www.google.com');
* // other actions...
* await browser.close();
* })();
* ```
*
* @public * @public
*/ */
export type PredefinedNetworkConditions = {[name: string]: NetworkConditions}; export const networkConditions: Readonly<{
'Slow 3G': NetworkConditions;
/** 'Fast 3G': NetworkConditions;
* @public }> = Object.freeze({
*/
export const networkConditions: PredefinedNetworkConditions = {
'Slow 3G': { 'Slow 3G': {
download: ((500 * 1000) / 8) * 0.8, download: ((500 * 1000) / 8) * 0.8,
upload: ((500 * 1000) / 8) * 0.8, upload: ((500 * 1000) / 8) * 0.8,
@ -35,4 +54,4 @@ export const networkConditions: PredefinedNetworkConditions = {
upload: ((750 * 1000) / 8) * 0.9, upload: ((750 * 1000) / 8) * 0.9,
latency: 150 * 3.75, latency: 150 * 3.75,
}, },
}; });

View File

@ -1,25 +1,38 @@
import {Protocol} from 'devtools-protocol'; import {Protocol} from 'devtools-protocol';
import {HTTPRequest} from './HTTPRequest.js'; import {HTTPRequest} from './HTTPRequest.js';
/**
* @internal
*/
export type QueuedEventGroup = { export type QueuedEventGroup = {
responseReceivedEvent: Protocol.Network.ResponseReceivedEvent; responseReceivedEvent: Protocol.Network.ResponseReceivedEvent;
loadingFinishedEvent?: Protocol.Network.LoadingFinishedEvent; loadingFinishedEvent?: Protocol.Network.LoadingFinishedEvent;
loadingFailedEvent?: Protocol.Network.LoadingFailedEvent; loadingFailedEvent?: Protocol.Network.LoadingFailedEvent;
}; };
/**
* @internal
*/
export type FetchRequestId = string; export type FetchRequestId = string;
export type NetworkRequestId = string;
type RedirectInfo = {
event: Protocol.Network.RequestWillBeSentEvent;
fetchRequestId?: FetchRequestId;
};
export type RedirectInfoList = RedirectInfo[];
/** /**
* @internal * @internal
* */
export type RedirectInfo = {
event: Protocol.Network.RequestWillBeSentEvent;
fetchRequestId?: FetchRequestId;
};
type RedirectInfoList = RedirectInfo[];
/**
* @internal
*/
export type NetworkRequestId = string;
/**
* Helper class to track network events by request ID * Helper class to track network events by request ID
*
* @internal
*/ */
export class NetworkEventManager { export class NetworkEventManager {
/* /*

View File

@ -17,7 +17,7 @@
import {Protocol} from 'devtools-protocol'; import {Protocol} from 'devtools-protocol';
import type {Readable} from 'stream'; import type {Readable} from 'stream';
import {Accessibility} from './Accessibility.js'; import {Accessibility} from './Accessibility.js';
import {assert, assertNever} from './assert.js'; import {assert} from './assert.js';
import {Browser, BrowserContext} from './Browser.js'; import {Browser, BrowserContext} from './Browser.js';
import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js'; import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js';
import {ConsoleMessage, ConsoleMessageType} from './ConsoleMessage.js'; import {ConsoleMessage, ConsoleMessageType} from './ConsoleMessage.js';
@ -51,6 +51,7 @@ import {TimeoutSettings} from './TimeoutSettings.js';
import {Tracing} from './Tracing.js'; import {Tracing} from './Tracing.js';
import {EvaluateFunc, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import { import {
createJSHandle,
debugError, debugError,
evaluationString, evaluationString,
getExceptionMessage, getExceptionMessage,
@ -67,7 +68,6 @@ import {
valueFromRemoteObject, valueFromRemoteObject,
waitForEvent, waitForEvent,
waitWithTimeout, waitWithTimeout,
_createJSHandle,
} from './util.js'; } from './util.js';
import {WebWorker} from './WebWorker.js'; import {WebWorker} from './WebWorker.js';
@ -1640,7 +1640,7 @@ export class Page extends EventEmitter {
this.#client this.#client
); );
const values = event.args.map(arg => { const values = event.args.map(arg => {
return _createJSHandle(context, arg); return createJSHandle(context, arg);
}); });
this.#addConsoleMessage(event.type, values, event.stackTrace); this.#addConsoleMessage(event.type, values, event.stackTrace);
} }
@ -2273,12 +2273,15 @@ export class Page extends EventEmitter {
} }
/** /**
* Emulates given device metrics and user agent. This method is a shortcut for * Emulates given device metrics and user agent.
* calling two methods: {@link Page.setUserAgent} and {@link Page.setViewport} *
* To aid emulation, Puppeteer provides a list of device descriptors that can * @remarks
* be obtained via the {@link Puppeteer.devices} `page.emulate` will resize * This method is a shortcut for calling two methods:
* the page. A lot of websites don't expect phones to change size, so you * {@link Page.setUserAgent} and {@link Page.setViewport} To aid emulation,
* should emulate before navigating to the page. * Puppeteer provides a list of device descriptors that can be obtained via
* {@link devices}. `page.emulate` will resize the page. A lot of websites
* don't expect phones to change size, so you should emulate before navigating
* to the page.
* @example * @example
* ```js * ```js
* const puppeteer = require('puppeteer'); * const puppeteer = require('puppeteer');
@ -2783,10 +2786,6 @@ export class Page extends EventEmitter {
// because it may be a 0-length file with no extension created beforehand // because it may be a 0-length file with no extension created beforehand
// (i.e. as a temp file). // (i.e. as a temp file).
if (options.type) { if (options.type) {
const type = options.type;
if (type !== 'png' && type !== 'jpeg' && type !== 'webp') {
assertNever(type, 'Unknown options.type value: ' + type);
}
screenshotType = screenshotType =
options.type as Protocol.Page.CaptureScreenshotRequestFormat; options.type as Protocol.Page.CaptureScreenshotRequestFormat;
} else if (options.path) { } else if (options.path) {

View File

@ -13,23 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import {puppeteerErrors, PuppeteerErrors} from './Errors.js';
import {ConnectionTransport} from './ConnectionTransport.js';
import {_devicesMap, DevicesMap} from './DeviceDescriptors.js';
import {Browser} from './Browser.js'; import {Browser} from './Browser.js';
import { import {BrowserConnectOptions, _connectToBrowser} from './BrowserConnector.js';
_registerCustomQueryHandler, import {ConnectionTransport} from './ConnectionTransport.js';
_unregisterCustomQueryHandler, import {devices} from './DeviceDescriptors.js';
_customQueryHandlerNames, import {errors} from './Errors.js';
_clearCustomQueryHandlers, import {networkConditions} from './NetworkConditions.js';
CustomQueryHandler,
} from './QueryHandler.js';
import {Product} from './Product.js'; import {Product} from './Product.js';
import {_connectToBrowser, BrowserConnectOptions} from './BrowserConnector.js';
import { import {
PredefinedNetworkConditions, clearCustomQueryHandlers,
networkConditions, CustomQueryHandler,
} from './NetworkConditions.js'; customQueryHandlerNames,
registerCustomQueryHandler,
unregisterCustomQueryHandler,
} from './QueryHandler.js';
/** /**
* Settings that are common to the Puppeteer class, regardless of environment. * Settings that are common to the Puppeteer class, regardless of environment.
@ -69,12 +66,6 @@ export class Puppeteer {
this._isPuppeteerCore = settings.isPuppeteerCore; this._isPuppeteerCore = settings.isPuppeteerCore;
this.connect = this.connect.bind(this); this.connect = this.connect.bind(this);
this.registerCustomQueryHandler =
this.registerCustomQueryHandler.bind(this);
this.unregisterCustomQueryHandler =
this.unregisterCustomQueryHandler.bind(this);
this.customQueryHandlerNames = this.customQueryHandlerNames.bind(this);
this.clearCustomQueryHandlers = this.clearCustomQueryHandlers.bind(this);
} }
/** /**
@ -90,120 +81,82 @@ export class Puppeteer {
} }
/** /**
* @remarks * @deprecated Import directly puppeteer.
* A list of devices to be used with `page.emulate(options)`. Actual list of devices can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts | src/common/DeviceDescriptors.ts}.
*
* @example * @example
* * ```ts
* ```js * import { devices } from 'puppeteer';
* const puppeteer = require('puppeteer');
* const iPhone = puppeteer.devices['iPhone 6'];
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.emulate(iPhone);
* await page.goto('https://www.google.com');
* // other actions...
* await browser.close();
* })();
* ``` * ```
*
*/ */
get devices(): DevicesMap { get devices(): typeof devices {
return _devicesMap; return devices;
} }
/** /**
* @remarks * @deprecated Import directly puppeteer.
*
* Puppeteer methods might throw errors if they are unable to fulfill a request.
* For example, `page.waitForSelector(selector[, options])` might fail if
* the selector doesn't match any nodes during the given timeframe.
*
* For certain types of errors Puppeteer uses specific error classes.
* These classes are available via `puppeteer.errors`.
*
* @example * @example
* An example of handling a timeout error: * ```ts
* ```js * import { errors } from 'puppeteer';
* try {
* await page.waitForSelector('.foo');
* } catch (e) {
* if (e instanceof puppeteer.errors.TimeoutError) {
* // Do something if this is a timeout.
* }
* }
* ``` * ```
*/ */
get errors(): PuppeteerErrors { get errors(): typeof errors {
return puppeteerErrors; return errors;
} }
/** /**
* @remarks * @deprecated Import directly puppeteer.
* Returns a list of network conditions to be used with `page.emulateNetworkConditions(networkConditions)`. Actual list of predefined conditions can be found in {@link https://github.com/puppeteer/puppeteer/blob/main/src/common/NetworkConditions.ts | src/common/NetworkConditions.ts}.
*
* @example * @example
* * ```ts
* ```js * import { networkConditions } from 'puppeteer';
* const puppeteer = require('puppeteer');
* const slow3G = puppeteer.networkConditions['Slow 3G'];
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.emulateNetworkConditions(slow3G);
* await page.goto('https://www.google.com');
* // other actions...
* await browser.close();
* })();
* ``` * ```
*
*/ */
get networkConditions(): PredefinedNetworkConditions { get networkConditions(): typeof networkConditions {
return networkConditions; return networkConditions;
} }
/** /**
* Registers a {@link CustomQueryHandler | custom query handler}. After * @deprecated Import directly puppeteer.
* registration, the handler can be used everywhere where a selector is
* expected by prepending the selection string with `<name>/`. The name is
* only allowed to consist of lower- and upper case latin letters.
* @example * @example
* ```ts
* import { registerCustomQueryHandler } from 'puppeteer';
* ``` * ```
* puppeteer.registerCustomQueryHandler('text', { });
* const aHandle = await page.$('text/…');
* ```
* @param name - The name that the custom query handler will be registered under.
* @param queryHandler - The {@link CustomQueryHandler | custom query handler} to
* register.
*/ */
registerCustomQueryHandler( registerCustomQueryHandler(
name: string, name: string,
queryHandler: CustomQueryHandler queryHandler: CustomQueryHandler
): void { ): void {
_registerCustomQueryHandler(name, queryHandler); return registerCustomQueryHandler(name, queryHandler);
} }
/** /**
* @param name - The name of the query handler to unregistered. * @deprecated Import directly puppeteer.
* @example
* ```ts
* import { unregisterCustomQueryHandler } from 'puppeteer';
* ```
*/ */
unregisterCustomQueryHandler(name: string): void { unregisterCustomQueryHandler(name: string): void {
_unregisterCustomQueryHandler(name); return unregisterCustomQueryHandler(name);
} }
/** /**
* @returns a list with the names of all registered custom query handlers. * @deprecated Import directly puppeteer.
* @example
* ```ts
* import { customQueryHandlerNames } from 'puppeteer';
* ```
*/ */
customQueryHandlerNames(): string[] { customQueryHandlerNames(): string[] {
return _customQueryHandlerNames(); return customQueryHandlerNames();
} }
/** /**
* Clears all registered handlers. * @deprecated Import directly puppeteer.
* @example
* ```ts
* import { clearCustomQueryHandlers } from 'puppeteer';
* ```
*/ */
clearCustomQueryHandlers(): void { clearCustomQueryHandlers(): void {
_clearCustomQueryHandlers(); return clearCustomQueryHandlers();
} }
} }

View File

@ -44,7 +44,7 @@ export interface InternalQueryHandler {
/** /**
* Contains two functions `queryOne` and `queryAll` that can * Contains two functions `queryOne` and `queryAll` that can
* be {@link Puppeteer.registerCustomQueryHandler | registered} * be {@link registerCustomQueryHandler | registered}
* as alternative querying strategies. The functions `queryOne` and `queryAll` * as alternative querying strategies. The functions `queryOne` and `queryAll`
* are executed in the page context. `queryOne` should take an `Element` and a * are executed in the page context. `queryOne` should take an `Element` and a
* selector string as argument and return a single `Element` or `null` if no * selector string as argument and return a single `Element` or `null` if no
@ -114,7 +114,7 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler {
return internalHandler; return internalHandler;
} }
const _defaultHandler = makeQueryHandler({ const defaultHandler = makeQueryHandler({
queryOne: (element: Element | Document, selector: string) => { queryOne: (element: Element | Document, selector: string) => {
return element.querySelector(selector); return element.querySelector(selector);
}, },
@ -180,9 +180,27 @@ const builtInHandlers = new Map([
const queryHandlers = new Map(builtInHandlers); const queryHandlers = new Map(builtInHandlers);
/** /**
* @internal * Registers a {@link CustomQueryHandler | custom query handler}.
*
* @remarks
* After registration, the handler can be used everywhere where a selector is
* expected by prepending the selection string with `<name>/`. The name is only
* allowed to consist of lower- and upper case latin letters.
*
* @example
* ```
* puppeteer.registerCustomQueryHandler('text', { });
* const aHandle = await page.$('text/…');
* ```
*
* @param name - The name that the custom query handler will be registered
* under.
* @param queryHandler - The {@link CustomQueryHandler | custom query handler}
* to register.
*
* @public
*/ */
export function _registerCustomQueryHandler( export function registerCustomQueryHandler(
name: string, name: string,
handler: CustomQueryHandler handler: CustomQueryHandler
): void { ): void {
@ -201,40 +219,46 @@ export function _registerCustomQueryHandler(
} }
/** /**
* @internal * @param name - The name of the query handler to unregistered.
*
* @public
*/ */
export function _unregisterCustomQueryHandler(name: string): void { export function unregisterCustomQueryHandler(name: string): void {
if (queryHandlers.has(name) && !builtInHandlers.has(name)) { if (queryHandlers.has(name) && !builtInHandlers.has(name)) {
queryHandlers.delete(name); queryHandlers.delete(name);
} }
} }
/** /**
* @internal * @returns a list with the names of all registered custom query handlers.
*
* @public
*/ */
export function _customQueryHandlerNames(): string[] { export function customQueryHandlerNames(): string[] {
return [...queryHandlers.keys()].filter(name => { return [...queryHandlers.keys()].filter(name => {
return !builtInHandlers.has(name); return !builtInHandlers.has(name);
}); });
} }
/** /**
* @internal * Clears all registered handlers.
*
* @public
*/ */
export function _clearCustomQueryHandlers(): void { export function clearCustomQueryHandlers(): void {
_customQueryHandlerNames().forEach(_unregisterCustomQueryHandler); customQueryHandlerNames().forEach(unregisterCustomQueryHandler);
} }
/** /**
* @internal * @internal
*/ */
export function _getQueryHandlerAndSelector(selector: string): { export function getQueryHandlerAndSelector(selector: string): {
updatedSelector: string; updatedSelector: string;
queryHandler: InternalQueryHandler; queryHandler: InternalQueryHandler;
} { } {
const hasCustomQueryHandler = /^[a-zA-Z]+\//.test(selector); const hasCustomQueryHandler = /^[a-zA-Z]+\//.test(selector);
if (!hasCustomQueryHandler) { if (!hasCustomQueryHandler) {
return {updatedSelector: selector, queryHandler: _defaultHandler}; return {updatedSelector: selector, queryHandler: defaultHandler};
} }
const index = selector.indexOf('/'); const index = selector.indexOf('/');

View File

@ -14,6 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
/**
* @internal
*/
export class TaskQueue { export class TaskQueue {
#chain: Promise<void>; #chain: Promise<void>;

View File

@ -18,6 +18,8 @@
* Asserts that the given value is truthy. * Asserts that the given value is truthy.
* @param value - some conditional statement * @param value - some conditional statement
* @param message - the error message to throw if the value is not truthy. * @param message - the error message to throw if the value is not truthy.
*
* @internal
*/ */
export const assert: (value: unknown, message?: string) => asserts value = ( export const assert: (value: unknown, message?: string) => asserts value = (
value, value,
@ -27,12 +29,3 @@ export const assert: (value: unknown, message?: string) => asserts value = (
throw new Error(message); throw new Error(message);
} }
}; };
export const assertNever: (
value: unknown,
message?: string
) => asserts value is never = (value, message) => {
if (value) {
throw new Error(message);
}
};

View File

@ -14,7 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
/* Use the global version if we're in the browser, else load the node-fetch module. */ /**
* Gets the global version if we're in the browser, else loads the node-fetch module.
*
* @internal
*/
export const getFetch = async (): Promise<typeof fetch> => { export const getFetch = async (): Promise<typeof fetch> => {
return (globalThis as any).fetch || (await import('cross-fetch')).fetch; return (globalThis as any).fetch || (await import('cross-fetch')).fetch;
}; };

View File

@ -17,16 +17,34 @@
import {JSHandle} from './JSHandle.js'; import {JSHandle} from './JSHandle.js';
import {ElementHandle} from './ElementHandle.js'; import {ElementHandle} from './ElementHandle.js';
/**
* @public
*/
export type Awaitable<T> = T | PromiseLike<T>; export type Awaitable<T> = T | PromiseLike<T>;
/**
* @public
*/
export type HandleFor<T> = T extends Element ? ElementHandle<T> : JSHandle<T>; export type HandleFor<T> = T extends Element ? ElementHandle<T> : JSHandle<T>;
/**
* @public
*/
export type HandleOr<T> = HandleFor<T> | JSHandle<T> | T; export type HandleOr<T> = HandleFor<T> | JSHandle<T> | T;
type FlattenHandle<T> = T extends HandleOr<infer U> ? U : never; /**
* @public
*/
export type FlattenHandle<T> = T extends HandleOr<infer U> ? U : never;
/**
* @public
*/
export type InnerParams<T extends unknown[]> = { export type InnerParams<T extends unknown[]> = {
[K in keyof T]: FlattenHandle<T[K]>; [K in keyof T]: FlattenHandle<T[K]>;
}; };
/**
* @public
*/
export type EvaluateFunc<T extends unknown[]> = ( export type EvaluateFunc<T extends unknown[]> = (
...params: InnerParams<T> ...params: InnerParams<T>
) => Awaitable<unknown>; ) => Awaitable<unknown>;

View File

@ -26,8 +26,14 @@ import {CommonEventEmitter} from './EventEmitter.js';
import {ExecutionContext} from './ExecutionContext.js'; import {ExecutionContext} from './ExecutionContext.js';
import {JSHandle} from './JSHandle.js'; import {JSHandle} from './JSHandle.js';
/**
* @internal
*/
export const debugError = debug('puppeteer:error'); export const debugError = debug('puppeteer:error');
/**
* @internal
*/
export function getExceptionMessage( export function getExceptionMessage(
exceptionDetails: Protocol.Runtime.ExceptionDetails exceptionDetails: Protocol.Runtime.ExceptionDetails
): string { ): string {
@ -52,6 +58,9 @@ export function getExceptionMessage(
return message; return message;
} }
/**
* @internal
*/
export function valueFromRemoteObject( export function valueFromRemoteObject(
remoteObject: Protocol.Runtime.RemoteObject remoteObject: Protocol.Runtime.RemoteObject
): any { ): any {
@ -79,6 +88,9 @@ export function valueFromRemoteObject(
return remoteObject.value; return remoteObject.value;
} }
/**
* @internal
*/
export async function releaseObject( export async function releaseObject(
client: CDPSession, client: CDPSession,
remoteObject: Protocol.Runtime.RemoteObject remoteObject: Protocol.Runtime.RemoteObject
@ -95,12 +107,18 @@ export async function releaseObject(
}); });
} }
/**
* @internal
*/
export interface PuppeteerEventListener { export interface PuppeteerEventListener {
emitter: CommonEventEmitter; emitter: CommonEventEmitter;
eventName: string | symbol; eventName: string | symbol;
handler: (...args: any[]) => void; handler: (...args: any[]) => void;
} }
/**
* @internal
*/
export function addEventListener( export function addEventListener(
emitter: CommonEventEmitter, emitter: CommonEventEmitter,
eventName: string | symbol, eventName: string | symbol,
@ -110,6 +128,9 @@ export function addEventListener(
return {emitter, eventName, handler}; return {emitter, eventName, handler};
} }
/**
* @internal
*/
export function removeEventListeners( export function removeEventListeners(
listeners: Array<{ listeners: Array<{
emitter: CommonEventEmitter; emitter: CommonEventEmitter;
@ -123,14 +144,23 @@ export function removeEventListeners(
listeners.length = 0; listeners.length = 0;
} }
/**
* @internal
*/
export const isString = (obj: unknown): obj is string => { export const isString = (obj: unknown): obj is string => {
return typeof obj === 'string' || obj instanceof String; return typeof obj === 'string' || obj instanceof String;
}; };
/**
* @internal
*/
export const isNumber = (obj: unknown): obj is number => { export const isNumber = (obj: unknown): obj is number => {
return typeof obj === 'number' || obj instanceof Number; return typeof obj === 'number' || obj instanceof Number;
}; };
/**
* @internal
*/
export async function waitForEvent<T>( export async function waitForEvent<T>(
emitter: CommonEventEmitter, emitter: CommonEventEmitter,
eventName: string | symbol, eventName: string | symbol,
@ -182,7 +212,7 @@ export async function waitForEvent<T>(
/** /**
* @internal * @internal
*/ */
export function _createJSHandle( export function createJSHandle(
context: ExecutionContext, context: ExecutionContext,
remoteObject: Protocol.Runtime.RemoteObject remoteObject: Protocol.Runtime.RemoteObject
): JSHandle | ElementHandle { ): JSHandle | ElementHandle {
@ -201,6 +231,9 @@ export function _createJSHandle(
return new JSHandle(context, context._client, remoteObject); return new JSHandle(context, context._client, remoteObject);
} }
/**
* @internal
*/
export function evaluationString( export function evaluationString(
fun: Function | string, fun: Function | string,
...args: unknown[] ...args: unknown[]
@ -220,6 +253,9 @@ export function evaluationString(
return `(${fun})(${args.map(serializeArgument).join(',')})`; return `(${fun})(${args.map(serializeArgument).join(',')})`;
} }
/**
* @internal
*/
export function pageBindingInitString(type: string, name: string): string { export function pageBindingInitString(type: string, name: string): string {
function addPageBinding(type: string, bindingName: string): void { function addPageBinding(type: string, bindingName: string): void {
/* Cast window to any here as we're about to add properties to it /* Cast window to any here as we're about to add properties to it
@ -247,6 +283,9 @@ export function pageBindingInitString(type: string, name: string): string {
return evaluationString(addPageBinding, type, name); return evaluationString(addPageBinding, type, name);
} }
/**
* @internal
*/
export function pageBindingDeliverResultString( export function pageBindingDeliverResultString(
name: string, name: string,
seq: number, seq: number,
@ -259,6 +298,9 @@ export function pageBindingDeliverResultString(
return evaluationString(deliverResult, name, seq, result); return evaluationString(deliverResult, name, seq, result);
} }
/**
* @internal
*/
export function pageBindingDeliverErrorString( export function pageBindingDeliverErrorString(
name: string, name: string,
seq: number, seq: number,
@ -279,6 +321,9 @@ export function pageBindingDeliverErrorString(
return evaluationString(deliverError, name, seq, message, stack); return evaluationString(deliverError, name, seq, message, stack);
} }
/**
* @internal
*/
export function pageBindingDeliverErrorValueString( export function pageBindingDeliverErrorValueString(
name: string, name: string,
seq: number, seq: number,
@ -291,6 +336,9 @@ export function pageBindingDeliverErrorValueString(
return evaluationString(deliverErrorValue, name, seq, value); return evaluationString(deliverErrorValue, name, seq, value);
} }
/**
* @internal
*/
export function makePredicateString( export function makePredicateString(
predicate: Function, predicate: Function,
predicateQueryHandler?: Function predicateQueryHandler?: Function
@ -334,6 +382,9 @@ export function makePredicateString(
})() `; })() `;
} }
/**
* @internal
*/
export async function waitWithTimeout<T>( export async function waitWithTimeout<T>(
promise: Promise<T>, promise: Promise<T>,
taskName: string, taskName: string,
@ -361,6 +412,9 @@ export async function waitWithTimeout<T>(
} }
} }
/**
* @internal
*/
export async function getReadableAsBuffer( export async function getReadableAsBuffer(
readable: Readable, readable: Readable,
path?: string path?: string
@ -396,6 +450,9 @@ export async function getReadableAsBuffer(
} }
} }
/**
* @internal
*/
export async function getReadableFromProtocolStream( export async function getReadableFromProtocolStream(
client: CDPSession, client: CDPSession,
handle: string handle: string
@ -426,17 +483,26 @@ export async function getReadableFromProtocolStream(
}); });
} }
interface ErrorLike extends Error { /**
* @internal
*/
export interface ErrorLike extends Error {
name: string; name: string;
message: string; message: string;
} }
/**
* @internal
*/
export function isErrorLike(obj: unknown): obj is ErrorLike { export function isErrorLike(obj: unknown): obj is ErrorLike {
return ( return (
typeof obj === 'object' && obj !== null && 'name' in obj && 'message' in obj typeof obj === 'object' && obj !== null && 'name' in obj && 'message' in obj
); );
} }
/**
* @internal
*/
export function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException { export function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException {
return ( return (
isErrorLike(obj) && isErrorLike(obj) &&

View File

@ -1,4 +1,7 @@
import {dirname} from 'path'; import {dirname} from 'path';
import {puppeteerDirname} from './compat.js'; import {puppeteerDirname} from './compat.js';
/**
* @internal
*/
export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); export const rootDirname = dirname(dirname(dirname(puppeteerDirname)));

View File

@ -14,4 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
/**
* @internal
*/
export const isNode = !!(typeof process !== 'undefined' && process.version); export const isNode = !!(typeof process !== 'undefined' && process.version);

View File

@ -1 +1,4 @@
/**
* @internal
*/
export const packageVersion = '15.1.1'; export const packageVersion = '15.1.1';

View File

@ -20,6 +20,9 @@ import {rootDirname} from './constants.js';
import {PuppeteerNode} from './node/Puppeteer.js'; import {PuppeteerNode} from './node/Puppeteer.js';
import {PUPPETEER_REVISIONS} from './revisions.js'; import {PUPPETEER_REVISIONS} from './revisions.js';
/**
* @internal
*/
export const initializePuppeteer = (packageName: string): PuppeteerNode => { export const initializePuppeteer = (packageName: string): PuppeteerNode => {
const isPuppeteerCore = packageName === 'puppeteer-core'; const isPuppeteerCore = packageName === 'puppeteer-core';
const puppeteerRootDirectory = sync(rootDirname); const puppeteerRootDirectory = sync(rootDirname);

View File

@ -71,6 +71,7 @@ const browserConfig = {
/** /**
* Supported platforms. * Supported platforms.
*
* @public * @public
*/ */
export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64'; export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64';
@ -100,10 +101,7 @@ function archiveName(
} }
} }
/** function downloadURL(
* @internal
*/
function _downloadURL(
product: Product, product: Product,
platform: Platform, platform: Platform,
host: string, host: string,
@ -282,7 +280,7 @@ export class BrowserFetcher {
* from the host. * from the host.
*/ */
canDownload(revision: string): Promise<boolean> { canDownload(revision: string): Promise<boolean> {
const url = _downloadURL( const url = downloadURL(
this.#product, this.#product,
this.#platform, this.#platform,
this.#downloadHost, this.#downloadHost,
@ -318,7 +316,7 @@ export class BrowserFetcher {
revision: string, revision: string,
progressCallback: (x: number, y: number) => void = (): void => {} progressCallback: (x: number, y: number) => void = (): void => {}
): Promise<BrowserFetcherRevisionInfo | undefined> { ): Promise<BrowserFetcherRevisionInfo | undefined> {
const url = _downloadURL( const url = downloadURL(
this.#product, this.#product,
this.#platform, this.#platform,
this.#downloadHost, this.#downloadHost,
@ -451,7 +449,7 @@ export class BrowserFetcher {
} else { } else {
throw new Error('Unsupported product: ' + this.#product); throw new Error('Unsupported product: ' + this.#product);
} }
const url = _downloadURL( const url = downloadURL(
this.#product, this.#product,
this.#platform, this.#platform,
this.#downloadHost, this.#downloadHost,

View File

@ -48,6 +48,9 @@ This means that, on future Puppeteer launches, Puppeteer might not be able to la
Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed. Please check your open processes and ensure that the browser processes that Puppeteer launched have been killed.
If you think this is a bug, please report it on the Puppeteer issue tracker.`; If you think this is a bug, please report it on the Puppeteer issue tracker.`;
/**
* @internal
*/
export class BrowserRunner { export class BrowserRunner {
#product: Product; #product: Product;
#executablePath: string; #executablePath: string;

View File

@ -18,6 +18,9 @@ import {ConnectionTransport} from '../common/ConnectionTransport.js';
import {packageVersion} from '../generated/version.js'; import {packageVersion} from '../generated/version.js';
import {promises as dns} from 'dns'; import {promises as dns} from 'dns';
/**
* @internal
*/
export class NodeWebSocketTransport implements ConnectionTransport { export class NodeWebSocketTransport implements ConnectionTransport {
static async create(urlString: string): Promise<NodeWebSocketTransport> { static async create(urlString: string): Promise<NodeWebSocketTransport> {
// TODO(jrandolf): Starting in Node 17, IPv6 is favoured over IPv4 due to a change // TODO(jrandolf): Starting in Node 17, IPv6 is favoured over IPv4 due to a change

View File

@ -22,6 +22,9 @@ import {
removeEventListeners, removeEventListeners,
} from '../common/util.js'; } from '../common/util.js';
/**
* @internal
*/
export class PipeTransport implements ConnectionTransport { export class PipeTransport implements ConnectionTransport {
#pipeWrite: NodeJS.WritableStream; #pipeWrite: NodeJS.WritableStream;
#eventListeners: PuppeteerEventListener[]; #eventListeners: PuppeteerEventListener[];

View File

@ -40,6 +40,9 @@ export interface ProductLauncher {
product: Product; product: Product;
} }
/**
* @internal
*/
export function executablePathForChannel( export function executablePathForChannel(
channel: ChromeReleaseChannel channel: ChromeReleaseChannel
): string { ): string {
@ -116,6 +119,9 @@ export function executablePathForChannel(
return chromePath; return chromePath;
} }
/**
* @internal
*/
export function resolveExecutablePath( export function resolveExecutablePath(
launcher: ChromeLauncher | FirefoxLauncher launcher: ChromeLauncher | FirefoxLauncher
): { ): {

View File

@ -39,14 +39,13 @@ export interface PuppeteerLaunchOptions
} }
/** /**
* Extends the main {@link Puppeteer} class with Node specific behaviour for fetching and * Extends the main {@link Puppeteer} class with Node specific behaviour for
* downloading browsers. * fetching and downloading browsers.
* *
* If you're using Puppeteer in a Node environment, this is the class you'll get * If you're using Puppeteer in a Node environment, this is the class you'll get
* when you run `require('puppeteer')` (or the equivalent ES `import`). * when you run `require('puppeteer')` (or the equivalent ES `import`).
* *
* @remarks * @remarks
*
* The most common method to use is {@link PuppeteerNode.launch | launch}, which * The most common method to use is {@link PuppeteerNode.launch | launch}, which
* is used to launch and connect to a new browser instance. * is used to launch and connect to a new browser instance.
* *
@ -107,8 +106,6 @@ export class PuppeteerNode extends Puppeteer {
/** /**
* This method attaches Puppeteer to an existing browser instance. * This method attaches Puppeteer to an existing browser instance.
* *
* @remarks
*
* @param options - Set of configurable options to set on the browser. * @param options - Set of configurable options to set on the browser.
* @returns Promise which resolves to browser instance. * @returns Promise which resolves to browser instance.
*/ */
@ -125,10 +122,6 @@ export class PuppeteerNode extends Puppeteer {
get _productName(): Product | undefined { get _productName(): Product | undefined {
return this.#productName; return this.#productName;
} }
/**
* @internal
*/
set _productName(name: Product | undefined) { set _productName(name: Product | undefined) {
if (this.#productName !== name) { if (this.#productName !== name) {
this._changedProduct = true; this._changedProduct = true;
@ -137,10 +130,8 @@ export class PuppeteerNode extends Puppeteer {
} }
/** /**
* Launches puppeteer and launches a browser instance with given arguments * Launches puppeteer and launches a browser instance with given arguments and
* and options when specified. * options when specified.
*
* @remarks
* *
* @example * @example
* You can use `ignoreDefaultArgs` to filter out `--mute-audio` from default arguments: * You can use `ignoreDefaultArgs` to filter out `--mute-audio` from default arguments:
@ -150,13 +141,20 @@ export class PuppeteerNode extends Puppeteer {
* }); * });
* ``` * ```
* *
* **NOTE** Puppeteer can also be used to control the Chrome browser, * @remarks
* but it works best with the version of Chromium it is bundled with. * **NOTE** Puppeteer can also be used to control the Chrome browser, but it
* There is no guarantee it will work with any other version. * works best with the version of Chromium it is bundled with. There is no
* Use `executablePath` option with extreme caution. * guarantee it will work with any other version. Use `executablePath` option
* If Google Chrome (rather than Chromium) is preferred, a {@link https://www.google.com/chrome/browser/canary.html | Chrome Canary} or {@link https://www.chromium.org/getting-involved/dev-channel | Dev Channel} build is suggested. * with extreme caution. If Google Chrome (rather than Chromium) is preferred,
* In `puppeteer.launch([options])`, any mention of Chromium also applies to Chrome. * a {@link https://www.google.com/chrome/browser/canary.html | Chrome Canary}
* See {@link https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/ | this article} for a description of the differences between Chromium and Chrome. {@link https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md | This article} describes some differences for Linux users. * or
* {@link https://www.chromium.org/getting-involved/dev-channel | Dev Channel}
* build is suggested. In `puppeteer.launch([options])`, any mention of
* Chromium also applies to Chrome. See
* {@link https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/ | this article}
* for a description of the differences between Chromium and Chrome.
* {@link https://chromium.googlesource.com/chromium/src/+/lkgr/docs/chromium_browser_vs_google_chrome.md | This article}
* describes some differences for Linux users.
* *
* @param options - Set of configurable options to set on the browser. * @param options - Set of configurable options to set on the browser.
* @returns Promise which resolves to browser instance. * @returns Promise which resolves to browser instance.
@ -170,13 +168,13 @@ export class PuppeteerNode extends Puppeteer {
/** /**
* @remarks * @remarks
* **NOTE** `puppeteer.executablePath()` is affected by the
* `PUPPETEER_EXECUTABLE_PATH` and `PUPPETEER_CHROMIUM_REVISION` environment
* variables.
* *
* **NOTE** `puppeteer.executablePath()` is affected by the `PUPPETEER_EXECUTABLE_PATH` * @returns A path where Puppeteer expects to find the bundled browser. The
* and `PUPPETEER_CHROMIUM_REVISION` environment variables. * browser binary might not be there if the download was skipped with the
* * `PUPPETEER_SKIP_DOWNLOAD` environment variable.
* @returns A path where Puppeteer expects to find the bundled browser.
* The browser binary might not be there if the download was skipped with
* the `PUPPETEER_SKIP_DOWNLOAD` environment variable.
*/ */
executablePath(channel?: string): string { executablePath(channel?: string): string {
return this._launcher.executablePath(channel); return this._launcher.executablePath(channel);
@ -211,11 +209,12 @@ export class PuppeteerNode extends Puppeteer {
} }
/** /**
* The name of the browser that is under automation (`"chrome"` or `"firefox"`) * The name of the browser that is under automation (`"chrome"` or
* `"firefox"`)
* *
* @remarks * @remarks
* The product is set by the `PUPPETEER_PRODUCT` environment variable or the `product` * The product is set by the `PUPPETEER_PRODUCT` environment variable or the
* option in `puppeteer.launch([options])` and defaults to `chrome`. * `product` option in `puppeteer.launch([options])` and defaults to `chrome`.
* Firefox support is experimental. * Firefox support is experimental.
*/ */
get product(): string { get product(): string {
@ -223,7 +222,6 @@ export class PuppeteerNode extends Puppeteer {
} }
/** /**
*
* @param options - Set of configurable options to set on the browser. * @param options - Set of configurable options to set on the browser.
* @returns The default flags that Chromium will be launched with. * @returns The default flags that Chromium will be launched with.
*/ */
@ -232,8 +230,8 @@ export class PuppeteerNode extends Puppeteer {
} }
/** /**
* @param options - Set of configurable options to specify the settings * @param options - Set of configurable options to specify the settings of the
* of the BrowserFetcher. * BrowserFetcher.
* @returns A new BrowserFetcher instance. * @returns A new BrowserFetcher instance.
*/ */
createBrowserFetcher(options: BrowserFetcherOptions): BrowserFetcher { createBrowserFetcher(options: BrowserFetcherOptions): BrowserFetcher {

View File

@ -23,11 +23,17 @@ import {PuppeteerNode} from './Puppeteer.js';
import createHttpsProxyAgent, {HttpsProxyAgentOptions} from 'https-proxy-agent'; import createHttpsProxyAgent, {HttpsProxyAgentOptions} from 'https-proxy-agent';
import {getProxyForUrl} from 'proxy-from-env'; import {getProxyForUrl} from 'proxy-from-env';
/**
* @internal
*/
const supportedProducts = { const supportedProducts = {
chrome: 'Chromium', chrome: 'Chromium',
firefox: 'Firefox Nightly', firefox: 'Firefox Nightly',
} as const; } as const;
/**
* @internal
*/
function getProduct(input: string): 'chrome' | 'firefox' { function getProduct(input: string): 'chrome' | 'firefox' {
if (input !== 'chrome' && input !== 'firefox') { if (input !== 'chrome' && input !== 'firefox') {
throw new Error(`Unsupported product ${input}`); throw new Error(`Unsupported product ${input}`);
@ -35,6 +41,9 @@ function getProduct(input: string): 'chrome' | 'firefox' {
return input; return input;
} }
/**
* @internal
*/
export async function downloadBrowser(): Promise<void> { export async function downloadBrowser(): Promise<void> {
const downloadHost = const downloadHost =
process.env['PUPPETEER_DOWNLOAD_HOST'] || process.env['PUPPETEER_DOWNLOAD_HOST'] ||
@ -209,6 +218,9 @@ export async function downloadBrowser(): Promise<void> {
} }
} }
/**
* @internal
*/
export function logPolitely(toBeLogged: unknown): void { export function logPolitely(toBeLogged: unknown): void {
const logLevel = process.env['npm_config_loglevel'] || ''; const logLevel = process.env['npm_config_loglevel'] || '';
const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1; const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1;

View File

@ -16,21 +16,19 @@
import {initializePuppeteer} from './initializePuppeteer.js'; import {initializePuppeteer} from './initializePuppeteer.js';
export * from './common/NetworkConditions.js';
export * from './common/QueryHandler.js';
export * from './common/DeviceDescriptors.js';
export * from './common/Errors.js';
const puppeteer = initializePuppeteer('puppeteer-core'); const puppeteer = initializePuppeteer('puppeteer-core');
export const { export const {
clearCustomQueryHandlers,
connect, connect,
createBrowserFetcher, createBrowserFetcher,
customQueryHandlerNames,
defaultArgs, defaultArgs,
devices,
errors,
executablePath, executablePath,
launch, launch,
networkConditions,
registerCustomQueryHandler,
unregisterCustomQueryHandler,
} = puppeteer; } = puppeteer;
export default puppeteer; export default puppeteer;

View File

@ -16,21 +16,22 @@
import {initializePuppeteer} from './initializePuppeteer.js'; import {initializePuppeteer} from './initializePuppeteer.js';
export * from './common/NetworkConditions.js';
export * from './common/QueryHandler.js';
export * from './common/DeviceDescriptors.js';
export * from './common/Errors.js';
/**
* @public
*/
const puppeteer = initializePuppeteer('puppeteer'); const puppeteer = initializePuppeteer('puppeteer');
export const { export const {
clearCustomQueryHandlers,
connect, connect,
createBrowserFetcher, createBrowserFetcher,
customQueryHandlerNames,
defaultArgs, defaultArgs,
devices,
errors,
executablePath, executablePath,
launch, launch,
networkConditions,
registerCustomQueryHandler,
unregisterCustomQueryHandler,
} = puppeteer; } = puppeteer;
export default puppeteer; export default puppeteer;

View File

@ -14,6 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
/**
* @internal
*/
export const PUPPETEER_REVISIONS = Object.freeze({ export const PUPPETEER_REVISIONS = Object.freeze({
chromium: '1011831', chromium: '1011831',
firefox: 'latest', firefox: 'latest',

View File

@ -1 +1,4 @@
/**
* @internal
*/
export const packageVersion = 'PACKAGE_VERSION'; export const packageVersion = 'PACKAGE_VERSION';

71
src/types.ts Normal file
View File

@ -0,0 +1,71 @@
// AUTOGENERATED - Use `utils/export_all.js` to regenerate.
export * from './compat.d.js';
export * from './constants.js';
export * from './environment.js';
export * from './initializePuppeteer.js';
export * from './puppeteer.js';
export * from './revisions.js';
// Exports from `common`
export * from './common/Accessibility.js';
export * from './common/AriaQueryHandler.js';
export * from './common/Browser.js';
export * from './common/BrowserConnector.js';
export * from './common/BrowserWebSocketTransport.js';
export * from './common/Connection.js';
export * from './common/ConnectionTransport.js';
export * from './common/ConsoleMessage.js';
export * from './common/Coverage.js';
export * from './common/DOMWorld.js';
export * from './common/Debug.js';
export * from './common/DeviceDescriptors.js';
export * from './common/Dialog.js';
export * from './common/ElementHandle.js';
export * from './common/EmulationManager.js';
export * from './common/Errors.js';
export * from './common/EventEmitter.js';
export * from './common/ExecutionContext.js';
export * from './common/FileChooser.js';
export * from './common/FrameManager.js';
export * from './common/HTTPRequest.js';
export * from './common/HTTPResponse.js';
export * from './common/Input.js';
export * from './common/JSHandle.js';
export * from './common/LifecycleWatcher.js';
export * from './common/NetworkConditions.js';
export * from './common/NetworkEventManager.js';
export * from './common/NetworkManager.js';
export * from './common/PDFOptions.js';
export * from './common/Page.js';
export * from './common/Product.js';
export * from './common/Puppeteer.js';
export * from './common/PuppeteerViewport.js';
export * from './common/QueryHandler.js';
export * from './common/SecurityDetails.js';
export * from './common/Target.js';
export * from './common/TaskQueue.js';
export * from './common/TimeoutSettings.js';
export * from './common/Tracing.js';
export * from './common/USKeyboardLayout.js';
export * from './common/WebWorker.js';
export * from './common/assert.js';
export * from './common/fetch.js';
export * from './common/types.js';
export * from './common/util.js';
// Exports from `node`
export * from './node/BrowserFetcher.js';
export * from './node/BrowserRunner.js';
export * from './node/ChromeLauncher.js';
export * from './node/FirefoxLauncher.js';
export * from './node/LaunchOptions.js';
export * from './node/NodeWebSocketTransport.js';
export * from './node/PipeTransport.js';
export * from './node/ProductLauncher.js';
export * from './node/Puppeteer.js';
export * from './node/install.js';
export * from './node/util.js';
// Exports from `generated`
export * from './generated/version.js';

View File

@ -24,8 +24,8 @@ import {
import { import {
Browser, Browser,
BrowserContext, BrowserContext,
Page, } from '../../lib/cjs/puppeteer/common/Browser.js';
} from '../../lib/cjs/puppeteer/api-docs-entry.js'; import {Page} from '../../lib/cjs/puppeteer/common/Page.js';
describeChromeOnly('OOPIF', function () { describeChromeOnly('OOPIF', function () {
/* We use a special browser for this test as we need the --site-per-process flag */ /* We use a special browser for this test as we need the --site-per-process flag */

30
utils/export_all.js Normal file
View File

@ -0,0 +1,30 @@
const {readdirSync, writeFileSync} = require('fs');
const {join, basename} = require('path');
const EXCLUDE_FILES = ['puppeteer-core.ts'];
let typesTs = '// AUTOGENERATED - Use `utils/export_all.js` to regenerate.\n';
typesTs += `\n`;
for (const file of readdirSync(join(__dirname, `../src`)).filter(filename => {
return (
filename.endsWith('ts') &&
!filename.startsWith('types') &&
!EXCLUDE_FILES.includes(filename)
);
})) {
typesTs += `export * from './${basename(file, '.ts')}.js';\n`;
}
for (const folder of ['common', 'node', 'generated']) {
typesTs += `\n// Exports from \`${folder}\`\n`;
for (const file of readdirSync(join(__dirname, `../src/${folder}`)).filter(
filename => {
return filename.endsWith('ts') && !EXCLUDE_FILES.includes(filename);
}
)) {
typesTs += `export * from './${folder}/${basename(file, '.ts')}.js';\n`;
}
}
writeFileSync(join(__dirname, '../src/types.ts'), typesTs);