diff --git a/.eslintignore b/.eslintignore index b52c33785ebde..5de5cd4a647ac 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,4 @@ doclint/ lib/ test-ts-types/ tsconfig.tsbuildinfo -vendor/ \ No newline at end of file +vendor/ diff --git a/.gitignore b/.gitignore index ffcf73067f0f0..d6552444210b4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ docs/api.html lib/ node_modules/ package-lock.json +puppeteer.api.json puppeteer*.tgz test-ts-types/**/dist/ test-ts-types/**/node_modules diff --git a/.prettierignore b/.prettierignore index 94574cbf04b16..f6fdcd13feaa3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,7 +5,6 @@ build/ CHANGELOG.md coverage/ doclint/ -docs-api-json/ lib/ node_modules/ package-lock.json @@ -14,4 +13,5 @@ test-ts-types/ test/assets/ tsconfig.tsbuildinfo vendor/ -yarn.lock \ No newline at end of file +yarn.lock +puppeteer.api.json \ No newline at end of file diff --git a/api-extractor.json b/api-extractor.json index 08a64da53c404..8a80ee1e3e0a9 100644 --- a/api-extractor.json +++ b/api-extractor.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "mainEntryPointFilePath": "/lib/cjs/puppeteer/api-docs-entry.d.ts", + "mainEntryPointFilePath": "/lib/esm/puppeteer/types.d.ts", "bundledPackages": [], "apiReport": { @@ -9,12 +9,13 @@ "docModel": { "enabled": true, - "apiJsonFilePath": "/docs-api-json/.api.json" + "apiJsonFilePath": "/docs/.api.json" }, "dtsRollup": { "enabled": true, - "untrimmedFilePath": "lib/types.d.ts" + "untrimmedFilePath": "", + "alphaTrimmedFilePath": "lib/types.d.ts" }, "tsdocMetadata": { diff --git a/compat/cjs/compat.ts b/compat/cjs/compat.ts index 1d3a49c8def54..782727e00e9ff 100644 --- a/compat/cjs/compat.ts +++ b/compat/cjs/compat.ts @@ -1,5 +1,8 @@ import {dirname} from 'path'; +/** + * @internal + */ let puppeteerDirname: string; try { diff --git a/compat/esm/compat.ts b/compat/esm/compat.ts index c257160b28bb6..8d747658705d1 100644 --- a/compat/esm/compat.ts +++ b/compat/esm/compat.ts @@ -4,6 +4,9 @@ import {fileURLToPath} from 'url'; const require = createRequire(import.meta.url); +/** + * @internal + */ let puppeteerDirname: string; try { diff --git a/package.json b/package.json index f549b41cdf286..f272313ba5c73 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "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 .", "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:docs": "npm run generate:types && node utils/remove-tag.js", "generate:docs:testing": "commonmark docs/api.md > docs/api.html", @@ -52,7 +52,6 @@ "doc": "node utils/doclint/cli.js", "commitlint": "commitlint --from=HEAD~1", "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:test": "tsc -b test", "build:tsc": "npm run clean:lib && tsc --version && (npm run build:tsc:cjs && npm run build:tsc:esm)", diff --git a/src/api-docs-entry.ts b/src/api-docs-entry.ts deleted file mode 100644 index 77a22e0f11663..0000000000000 --- a/src/api-docs-entry.ts +++ /dev/null @@ -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; - } -): Promise; - -/** - * @public - * {@inheritDoc PuppeteerNode.connect} - */ -export declare function connect(options: ConnectOptions): Promise; - -/** - * @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; diff --git a/src/common/BrowserWebSocketTransport.ts b/src/common/BrowserWebSocketTransport.ts index abfadec6a829f..5fe32e6526e7e 100644 --- a/src/common/BrowserWebSocketTransport.ts +++ b/src/common/BrowserWebSocketTransport.ts @@ -15,6 +15,9 @@ */ import {ConnectionTransport} from './ConnectionTransport.js'; +/** + * @internal + */ export class BrowserWebSocketTransport implements ConnectionTransport { static create(url: string): Promise { return new Promise((resolve, reject) => { diff --git a/src/common/DOMWorld.ts b/src/common/DOMWorld.ts index 713ad16f60b3d..64c2b6edd2845 100644 --- a/src/common/DOMWorld.ts +++ b/src/common/DOMWorld.ts @@ -24,7 +24,7 @@ import {Frame, FrameManager} from './FrameManager.js'; import {MouseButton} from './Input.js'; import {JSHandle} from './JSHandle.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; -import {_getQueryHandlerAndSelector} from './QueryHandler.js'; +import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {TimeoutSettings} from './TimeoutSettings.js'; import {EvaluateFunc, HandleFor} from './types.js'; import { @@ -653,7 +653,7 @@ export class DOMWorld { options: WaitForSelectorOptions ): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert(queryHandler.waitFor, 'Query handler does not support waiting'); return queryHandler.waitFor(this, updatedSelector, options); } diff --git a/src/common/Debug.ts b/src/common/Debug.ts index d281e1cc0c79b..3aaa9806cb7a8 100644 --- a/src/common/Debug.ts +++ b/src/common/Debug.ts @@ -25,14 +25,10 @@ declare global { * A debug function that can be used in any environment. * * @remarks - * * If used in Node, it falls back to the * {@link https://www.npmjs.com/package/debug | debug module}. In the browser it * 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: * * ``` @@ -56,6 +52,11 @@ declare global { * log('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) => { if (isNode) { diff --git a/src/common/DeviceDescriptors.ts b/src/common/DeviceDescriptors.ts index fc2cfc20b85f3..934633c44b277 100644 --- a/src/common/DeviceDescriptors.ts +++ b/src/common/DeviceDescriptors.ts @@ -30,7 +30,7 @@ export interface Device { }; } -const devices: Device[] = [ +const deviceArray: Device[] = [ { name: 'Blackberry PlayBook', 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) { - _devicesMap[device.name] = device; +for (const device of deviceArray) { + devices[device.name] = device; } + +export {devices}; diff --git a/src/common/ElementHandle.ts b/src/common/ElementHandle.ts index 9429b1d6e2134..904b492271152 100644 --- a/src/common/ElementHandle.ts +++ b/src/common/ElementHandle.ts @@ -8,14 +8,13 @@ import { BoundingBox, BoxModel, ClickOptions, - computeQuadArea, JSHandle, Offset, Point, PressOptions, } from './JSHandle.js'; import {Page, ScreenshotOptions} from './Page.js'; -import {_getQueryHandlerAndSelector} from './QueryHandler.js'; +import {getQueryHandlerAndSelector} from './QueryHandler.js'; import {EvaluateFunc} from './types.js'; import {KeyInput} from './USKeyboardLayout.js'; import {debugError, isString} from './util.js'; @@ -841,7 +840,7 @@ export class ElementHandle< async $(selector: string): Promise; async $(selector: string): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert( queryHandler.queryOne, 'Cannot handle queries for a single element with the given selector' @@ -866,7 +865,7 @@ export class ElementHandle< async $$(selector: string): Promise; async $$(selector: string): Promise { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert( queryHandler.queryAll, 'Cannot handle queries for a multiple element with the given selector' @@ -986,7 +985,7 @@ export class ElementHandle< ...args: Params ): Promise>> { const {updatedSelector, queryHandler} = - _getQueryHandlerAndSelector(selector); + getQueryHandlerAndSelector(selector); assert(queryHandler.queryAllArray); const arrayHandle = await queryHandler.queryAllArray(this, updatedSelector); const result = await arrayHandle.evaluate(pageFunction, ...args); @@ -1046,3 +1045,16 @@ export class ElementHandle< }, 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); +} diff --git a/src/common/EmulationManager.ts b/src/common/EmulationManager.ts index 0c2af6b684f11..ba108d3124871 100644 --- a/src/common/EmulationManager.ts +++ b/src/common/EmulationManager.ts @@ -17,6 +17,9 @@ import {CDPSession} from './Connection.js'; import {Viewport} from './PuppeteerViewport.js'; import {Protocol} from 'devtools-protocol'; +/** + * @internal + */ export class EmulationManager { #client: CDPSession; #emulatingMobile = false; diff --git a/src/common/Errors.ts b/src/common/Errors.ts index fbd23c3abea1f..e153780028530 100644 --- a/src/common/Errors.ts +++ b/src/common/Errors.ts @@ -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 - * - * Example operations are {@link Page.waitForSelector | page.waitForSelector} - * or {@link PuppeteerNode.launch | puppeteer.launch}. + * Example operations are {@link Page.waitForSelector | page.waitForSelector} or + * {@link PuppeteerNode.launch | puppeteer.launch}. * * @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 */ -export const puppeteerErrors: PuppeteerErrors = Object.freeze({ +export const errors: PuppeteerErrors = Object.freeze({ TimeoutError, ProtocolError, }); diff --git a/src/common/Events.ts b/src/common/Events.ts deleted file mode 100644 index 76bca06701986..0000000000000 --- a/src/common/Events.ts +++ /dev/null @@ -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; diff --git a/src/common/ExecutionContext.ts b/src/common/ExecutionContext.ts index 3615b39c74f74..52018be124a6d 100644 --- a/src/common/ExecutionContext.ts +++ b/src/common/ExecutionContext.ts @@ -26,7 +26,7 @@ import { getExceptionMessage, isString, valueFromRemoteObject, - _createJSHandle, + createJSHandle, } from './util.js'; /** @@ -253,7 +253,7 @@ export class ExecutionContext { return returnByValue ? valueFromRemoteObject(remoteObject) - : _createJSHandle(this, remoteObject); + : createJSHandle(this, remoteObject); } if (typeof pageFunction !== 'function') { @@ -309,7 +309,7 @@ export class ExecutionContext { } return returnByValue ? valueFromRemoteObject(remoteObject) - : _createJSHandle(this, remoteObject); + : createJSHandle(this, remoteObject); function convertArgument( this: ExecutionContext, @@ -407,7 +407,7 @@ export class ExecutionContext { const response = await this._client.send('Runtime.queryObjects', { prototypeObjectId: prototypeHandle._remoteObject.objectId, }); - return _createJSHandle(this, response.objects) as HandleFor; + return createJSHandle(this, response.objects) as HandleFor; } /** @@ -420,7 +420,7 @@ export class ExecutionContext { backendNodeId: backendNodeId, executionContextId: this._contextId, }); - return _createJSHandle(this, object) as ElementHandle; + return createJSHandle(this, object) as ElementHandle; } /** diff --git a/src/common/JSHandle.ts b/src/common/JSHandle.ts index 4f540d86c20f5..f6eb085ef3877 100644 --- a/src/common/JSHandle.ts +++ b/src/common/JSHandle.ts @@ -20,7 +20,7 @@ import {CDPSession} from './Connection.js'; import {EvaluateFunc, HandleFor, HandleOr} from './types.js'; import {ExecutionContext} from './ExecutionContext.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'; /** @@ -222,7 +222,7 @@ export class JSHandle { if (!property.enumerable || !property.value) { continue; } - result.set(property.name, _createJSHandle(this.#context, property.value)); + result.set(property.name, createJSHandle(this.#context, property.value)); } return result; } @@ -345,16 +345,3 @@ export interface Point { x: 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); -} diff --git a/src/common/NetworkConditions.ts b/src/common/NetworkConditions.ts index b3bbc5d4b56f3..ca79da1ea3608 100644 --- a/src/common/NetworkConditions.ts +++ b/src/common/NetworkConditions.ts @@ -17,14 +17,33 @@ 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 */ -export type PredefinedNetworkConditions = {[name: string]: NetworkConditions}; - -/** - * @public - */ -export const networkConditions: PredefinedNetworkConditions = { +export const networkConditions: Readonly<{ + 'Slow 3G': NetworkConditions; + 'Fast 3G': NetworkConditions; +}> = Object.freeze({ 'Slow 3G': { download: ((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, latency: 150 * 3.75, }, -}; +}); diff --git a/src/common/NetworkEventManager.ts b/src/common/NetworkEventManager.ts index 33ae4cce938a7..9ea138cc65fc3 100644 --- a/src/common/NetworkEventManager.ts +++ b/src/common/NetworkEventManager.ts @@ -1,25 +1,38 @@ import {Protocol} from 'devtools-protocol'; import {HTTPRequest} from './HTTPRequest.js'; +/** + * @internal + */ export type QueuedEventGroup = { responseReceivedEvent: Protocol.Network.ResponseReceivedEvent; loadingFinishedEvent?: Protocol.Network.LoadingFinishedEvent; loadingFailedEvent?: Protocol.Network.LoadingFailedEvent; }; +/** + * @internal + */ export type FetchRequestId = string; -export type NetworkRequestId = string; -type RedirectInfo = { +/** + * @internal + */ +export type RedirectInfo = { event: Protocol.Network.RequestWillBeSentEvent; fetchRequestId?: FetchRequestId; }; -export type RedirectInfoList = RedirectInfo[]; +type RedirectInfoList = RedirectInfo[]; /** * @internal - * + */ +export type NetworkRequestId = string; + +/** * Helper class to track network events by request ID + * + * @internal */ export class NetworkEventManager { /* diff --git a/src/common/Page.ts b/src/common/Page.ts index 4a3e471f04ccb..2e5754e534387 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -17,7 +17,7 @@ import {Protocol} from 'devtools-protocol'; import type {Readable} from 'stream'; import {Accessibility} from './Accessibility.js'; -import {assert, assertNever} from './assert.js'; +import {assert} from './assert.js'; import {Browser, BrowserContext} from './Browser.js'; import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js'; import {ConsoleMessage, ConsoleMessageType} from './ConsoleMessage.js'; @@ -51,6 +51,7 @@ import {TimeoutSettings} from './TimeoutSettings.js'; import {Tracing} from './Tracing.js'; import {EvaluateFunc, HandleFor} from './types.js'; import { + createJSHandle, debugError, evaluationString, getExceptionMessage, @@ -67,7 +68,6 @@ import { valueFromRemoteObject, waitForEvent, waitWithTimeout, - _createJSHandle, } from './util.js'; import {WebWorker} from './WebWorker.js'; @@ -1640,7 +1640,7 @@ export class Page extends EventEmitter { this.#client ); const values = event.args.map(arg => { - return _createJSHandle(context, arg); + return createJSHandle(context, arg); }); 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 - * calling two methods: {@link Page.setUserAgent} and {@link Page.setViewport} - * To aid emulation, Puppeteer provides a list of device descriptors that can - * be obtained via the {@link Puppeteer.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. + * Emulates given device metrics and user agent. + * + * @remarks + * This method is a shortcut for calling two methods: + * {@link Page.setUserAgent} and {@link Page.setViewport} To aid emulation, + * 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 * ```js * 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 // (i.e. as a temp file). if (options.type) { - const type = options.type; - if (type !== 'png' && type !== 'jpeg' && type !== 'webp') { - assertNever(type, 'Unknown options.type value: ' + type); - } screenshotType = options.type as Protocol.Page.CaptureScreenshotRequestFormat; } else if (options.path) { diff --git a/src/common/Puppeteer.ts b/src/common/Puppeteer.ts index 86b7073880975..085d5b8fa0f2f 100644 --- a/src/common/Puppeteer.ts +++ b/src/common/Puppeteer.ts @@ -13,23 +13,20 @@ * See the License for the specific language governing permissions and * 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 {BrowserConnectOptions, _connectToBrowser} from './BrowserConnector.js'; +import {ConnectionTransport} from './ConnectionTransport.js'; +import {devices} from './DeviceDescriptors.js'; +import {errors} from './Errors.js'; +import {networkConditions} from './NetworkConditions.js'; +import {Product} from './Product.js'; import { - _registerCustomQueryHandler, - _unregisterCustomQueryHandler, - _customQueryHandlerNames, - _clearCustomQueryHandlers, + clearCustomQueryHandlers, CustomQueryHandler, + customQueryHandlerNames, + registerCustomQueryHandler, + unregisterCustomQueryHandler, } from './QueryHandler.js'; -import {Product} from './Product.js'; -import {_connectToBrowser, BrowserConnectOptions} from './BrowserConnector.js'; -import { - PredefinedNetworkConditions, - networkConditions, -} from './NetworkConditions.js'; /** * Settings that are common to the Puppeteer class, regardless of environment. @@ -69,12 +66,6 @@ export class Puppeteer { this._isPuppeteerCore = settings.isPuppeteerCore; 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 - * 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}. - * + * @deprecated Import directly puppeteer. * @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(); - * })(); + * ```ts + * import { devices } from 'puppeteer'; * ``` - * */ - get devices(): DevicesMap { - return _devicesMap; + get devices(): typeof devices { + return devices; } /** - * @remarks - * - * 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`. - * + * @deprecated Import directly puppeteer. * @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. - * } - * } + * ```ts + * import { errors } from 'puppeteer'; * ``` */ - get errors(): PuppeteerErrors { - return puppeteerErrors; + get errors(): typeof errors { + return errors; } /** - * @remarks - * 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}. - * + * @deprecated Import directly puppeteer. * @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(); - * })(); + * ```ts + * import { networkConditions } from 'puppeteer'; * ``` - * */ - get networkConditions(): PredefinedNetworkConditions { + get networkConditions(): typeof networkConditions { return networkConditions; } /** - * Registers a {@link CustomQueryHandler | custom query handler}. After - * registration, the handler can be used everywhere where a selector is - * expected by prepending the selection string with `/`. The name is - * only allowed to consist of lower- and upper case latin letters. + * @deprecated Import directly puppeteer. * @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( name: string, queryHandler: CustomQueryHandler ): 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); + 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[] { - return _customQueryHandlerNames(); + return customQueryHandlerNames(); } /** - * Clears all registered handlers. + * @deprecated Import directly puppeteer. + * @example + * ```ts + * import { clearCustomQueryHandlers } from 'puppeteer'; + * ``` */ clearCustomQueryHandlers(): void { - _clearCustomQueryHandlers(); + return clearCustomQueryHandlers(); } } diff --git a/src/common/QueryHandler.ts b/src/common/QueryHandler.ts index b66385f47dbda..80ada7a0d5eb6 100644 --- a/src/common/QueryHandler.ts +++ b/src/common/QueryHandler.ts @@ -44,7 +44,7 @@ export interface InternalQueryHandler { /** * 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` * 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 @@ -114,7 +114,7 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler { return internalHandler; } -const _defaultHandler = makeQueryHandler({ +const defaultHandler = makeQueryHandler({ queryOne: (element: Element | Document, selector: string) => { return element.querySelector(selector); }, @@ -180,9 +180,27 @@ const builtInHandlers = new Map([ 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 `/`. 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, handler: CustomQueryHandler ): 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)) { 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 !builtInHandlers.has(name); }); } /** - * @internal + * Clears all registered handlers. + * + * @public */ -export function _clearCustomQueryHandlers(): void { - _customQueryHandlerNames().forEach(_unregisterCustomQueryHandler); +export function clearCustomQueryHandlers(): void { + customQueryHandlerNames().forEach(unregisterCustomQueryHandler); } /** * @internal */ -export function _getQueryHandlerAndSelector(selector: string): { +export function getQueryHandlerAndSelector(selector: string): { updatedSelector: string; queryHandler: InternalQueryHandler; } { const hasCustomQueryHandler = /^[a-zA-Z]+\//.test(selector); if (!hasCustomQueryHandler) { - return {updatedSelector: selector, queryHandler: _defaultHandler}; + return {updatedSelector: selector, queryHandler: defaultHandler}; } const index = selector.indexOf('/'); diff --git a/src/common/TaskQueue.ts b/src/common/TaskQueue.ts index 1403f2ee95e6b..97cfe7c769c6f 100644 --- a/src/common/TaskQueue.ts +++ b/src/common/TaskQueue.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @internal + */ export class TaskQueue { #chain: Promise; diff --git a/src/common/assert.ts b/src/common/assert.ts index 232c84d51b7be..bd8b10e731829 100644 --- a/src/common/assert.ts +++ b/src/common/assert.ts @@ -18,6 +18,8 @@ * Asserts that the given value is truthy. * @param value - some conditional statement * @param message - the error message to throw if the value is not truthy. + * + * @internal */ export const assert: (value: unknown, message?: string) => asserts value = ( value, @@ -27,12 +29,3 @@ export const assert: (value: unknown, message?: string) => asserts value = ( throw new Error(message); } }; - -export const assertNever: ( - value: unknown, - message?: string -) => asserts value is never = (value, message) => { - if (value) { - throw new Error(message); - } -}; diff --git a/src/common/fetch.ts b/src/common/fetch.ts index 218c178986c65..5f13a352885fe 100644 --- a/src/common/fetch.ts +++ b/src/common/fetch.ts @@ -14,7 +14,11 @@ * 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 => { return (globalThis as any).fetch || (await import('cross-fetch')).fetch; }; diff --git a/src/common/types.ts b/src/common/types.ts index 4bbe8ab2f38a2..a5142314375c3 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -17,16 +17,34 @@ import {JSHandle} from './JSHandle.js'; import {ElementHandle} from './ElementHandle.js'; +/** + * @public + */ export type Awaitable = T | PromiseLike; +/** + * @public + */ export type HandleFor = T extends Element ? ElementHandle : JSHandle; +/** + * @public + */ export type HandleOr = HandleFor | JSHandle | T; -type FlattenHandle = T extends HandleOr ? U : never; +/** + * @public + */ +export type FlattenHandle = T extends HandleOr ? U : never; +/** + * @public + */ export type InnerParams = { [K in keyof T]: FlattenHandle; }; +/** + * @public + */ export type EvaluateFunc = ( ...params: InnerParams ) => Awaitable; diff --git a/src/common/util.ts b/src/common/util.ts index 0ca5715f09bc9..dc237b0e6a883 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -26,8 +26,14 @@ import {CommonEventEmitter} from './EventEmitter.js'; import {ExecutionContext} from './ExecutionContext.js'; import {JSHandle} from './JSHandle.js'; +/** + * @internal + */ export const debugError = debug('puppeteer:error'); +/** + * @internal + */ export function getExceptionMessage( exceptionDetails: Protocol.Runtime.ExceptionDetails ): string { @@ -52,6 +58,9 @@ export function getExceptionMessage( return message; } +/** + * @internal + */ export function valueFromRemoteObject( remoteObject: Protocol.Runtime.RemoteObject ): any { @@ -79,6 +88,9 @@ export function valueFromRemoteObject( return remoteObject.value; } +/** + * @internal + */ export async function releaseObject( client: CDPSession, remoteObject: Protocol.Runtime.RemoteObject @@ -95,12 +107,18 @@ export async function releaseObject( }); } +/** + * @internal + */ export interface PuppeteerEventListener { emitter: CommonEventEmitter; eventName: string | symbol; handler: (...args: any[]) => void; } +/** + * @internal + */ export function addEventListener( emitter: CommonEventEmitter, eventName: string | symbol, @@ -110,6 +128,9 @@ export function addEventListener( return {emitter, eventName, handler}; } +/** + * @internal + */ export function removeEventListeners( listeners: Array<{ emitter: CommonEventEmitter; @@ -123,14 +144,23 @@ export function removeEventListeners( listeners.length = 0; } +/** + * @internal + */ export const isString = (obj: unknown): obj is string => { return typeof obj === 'string' || obj instanceof String; }; +/** + * @internal + */ export const isNumber = (obj: unknown): obj is number => { return typeof obj === 'number' || obj instanceof Number; }; +/** + * @internal + */ export async function waitForEvent( emitter: CommonEventEmitter, eventName: string | symbol, @@ -182,7 +212,7 @@ export async function waitForEvent( /** * @internal */ -export function _createJSHandle( +export function createJSHandle( context: ExecutionContext, remoteObject: Protocol.Runtime.RemoteObject ): JSHandle | ElementHandle { @@ -201,6 +231,9 @@ export function _createJSHandle( return new JSHandle(context, context._client, remoteObject); } +/** + * @internal + */ export function evaluationString( fun: Function | string, ...args: unknown[] @@ -220,6 +253,9 @@ export function evaluationString( return `(${fun})(${args.map(serializeArgument).join(',')})`; } +/** + * @internal + */ export function pageBindingInitString(type: string, name: string): string { function addPageBinding(type: string, bindingName: string): void { /* 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); } +/** + * @internal + */ export function pageBindingDeliverResultString( name: string, seq: number, @@ -259,6 +298,9 @@ export function pageBindingDeliverResultString( return evaluationString(deliverResult, name, seq, result); } +/** + * @internal + */ export function pageBindingDeliverErrorString( name: string, seq: number, @@ -279,6 +321,9 @@ export function pageBindingDeliverErrorString( return evaluationString(deliverError, name, seq, message, stack); } +/** + * @internal + */ export function pageBindingDeliverErrorValueString( name: string, seq: number, @@ -291,6 +336,9 @@ export function pageBindingDeliverErrorValueString( return evaluationString(deliverErrorValue, name, seq, value); } +/** + * @internal + */ export function makePredicateString( predicate: Function, predicateQueryHandler?: Function @@ -334,6 +382,9 @@ export function makePredicateString( })() `; } +/** + * @internal + */ export async function waitWithTimeout( promise: Promise, taskName: string, @@ -361,6 +412,9 @@ export async function waitWithTimeout( } } +/** + * @internal + */ export async function getReadableAsBuffer( readable: Readable, path?: string @@ -396,6 +450,9 @@ export async function getReadableAsBuffer( } } +/** + * @internal + */ export async function getReadableFromProtocolStream( client: CDPSession, handle: string @@ -426,17 +483,26 @@ export async function getReadableFromProtocolStream( }); } -interface ErrorLike extends Error { +/** + * @internal + */ +export interface ErrorLike extends Error { name: string; message: string; } +/** + * @internal + */ export function isErrorLike(obj: unknown): obj is ErrorLike { return ( typeof obj === 'object' && obj !== null && 'name' in obj && 'message' in obj ); } +/** + * @internal + */ export function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException { return ( isErrorLike(obj) && diff --git a/src/constants.ts b/src/constants.ts index dd9726d567921..d8e562ccec5fd 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,7 @@ import {dirname} from 'path'; import {puppeteerDirname} from './compat.js'; +/** + * @internal + */ export const rootDirname = dirname(dirname(dirname(puppeteerDirname))); diff --git a/src/environment.ts b/src/environment.ts index f7d869775bfc4..5ceca84a0e333 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -14,4 +14,7 @@ * limitations under the License. */ +/** + * @internal + */ export const isNode = !!(typeof process !== 'undefined' && process.version); diff --git a/src/generated/version.ts b/src/generated/version.ts index c2f6a18505bc1..86e1da0f5a71f 100644 --- a/src/generated/version.ts +++ b/src/generated/version.ts @@ -1 +1,4 @@ +/** + * @internal + */ export const packageVersion = '15.1.1'; diff --git a/src/initializePuppeteer.ts b/src/initializePuppeteer.ts index 0b73390556ad0..224e498e5882b 100644 --- a/src/initializePuppeteer.ts +++ b/src/initializePuppeteer.ts @@ -20,6 +20,9 @@ import {rootDirname} from './constants.js'; import {PuppeteerNode} from './node/Puppeteer.js'; import {PUPPETEER_REVISIONS} from './revisions.js'; +/** + * @internal + */ export const initializePuppeteer = (packageName: string): PuppeteerNode => { const isPuppeteerCore = packageName === 'puppeteer-core'; const puppeteerRootDirectory = sync(rootDirname); diff --git a/src/node/BrowserFetcher.ts b/src/node/BrowserFetcher.ts index 1407483ed5b09..01865f6a4d558 100644 --- a/src/node/BrowserFetcher.ts +++ b/src/node/BrowserFetcher.ts @@ -71,6 +71,7 @@ const browserConfig = { /** * Supported platforms. + * * @public */ export type Platform = 'linux' | 'mac' | 'mac_arm' | 'win32' | 'win64'; @@ -100,10 +101,7 @@ function archiveName( } } -/** - * @internal - */ -function _downloadURL( +function downloadURL( product: Product, platform: Platform, host: string, @@ -282,7 +280,7 @@ export class BrowserFetcher { * from the host. */ canDownload(revision: string): Promise { - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, @@ -318,7 +316,7 @@ export class BrowserFetcher { revision: string, progressCallback: (x: number, y: number) => void = (): void => {} ): Promise { - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, @@ -451,7 +449,7 @@ export class BrowserFetcher { } else { throw new Error('Unsupported product: ' + this.#product); } - const url = _downloadURL( + const url = downloadURL( this.#product, this.#platform, this.#downloadHost, diff --git a/src/node/BrowserRunner.ts b/src/node/BrowserRunner.ts index 34b10b000342e..bdcdda75f0ed2 100644 --- a/src/node/BrowserRunner.ts +++ b/src/node/BrowserRunner.ts @@ -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. If you think this is a bug, please report it on the Puppeteer issue tracker.`; +/** + * @internal + */ export class BrowserRunner { #product: Product; #executablePath: string; diff --git a/src/node/NodeWebSocketTransport.ts b/src/node/NodeWebSocketTransport.ts index bf7492025e197..5596d10b46ab1 100644 --- a/src/node/NodeWebSocketTransport.ts +++ b/src/node/NodeWebSocketTransport.ts @@ -18,6 +18,9 @@ import {ConnectionTransport} from '../common/ConnectionTransport.js'; import {packageVersion} from '../generated/version.js'; import {promises as dns} from 'dns'; +/** + * @internal + */ export class NodeWebSocketTransport implements ConnectionTransport { static async create(urlString: string): Promise { // TODO(jrandolf): Starting in Node 17, IPv6 is favoured over IPv4 due to a change diff --git a/src/node/PipeTransport.ts b/src/node/PipeTransport.ts index 511d7fb6ab512..a622a9bbbb5b0 100644 --- a/src/node/PipeTransport.ts +++ b/src/node/PipeTransport.ts @@ -22,6 +22,9 @@ import { removeEventListeners, } from '../common/util.js'; +/** + * @internal + */ export class PipeTransport implements ConnectionTransport { #pipeWrite: NodeJS.WritableStream; #eventListeners: PuppeteerEventListener[]; diff --git a/src/node/ProductLauncher.ts b/src/node/ProductLauncher.ts index 8d5c233d6ba5d..a1d7c84f4600a 100644 --- a/src/node/ProductLauncher.ts +++ b/src/node/ProductLauncher.ts @@ -40,6 +40,9 @@ export interface ProductLauncher { product: Product; } +/** + * @internal + */ export function executablePathForChannel( channel: ChromeReleaseChannel ): string { @@ -116,6 +119,9 @@ export function executablePathForChannel( return chromePath; } +/** + * @internal + */ export function resolveExecutablePath( launcher: ChromeLauncher | FirefoxLauncher ): { diff --git a/src/node/Puppeteer.ts b/src/node/Puppeteer.ts index fb9af91afc453..fa994f02a8582 100644 --- a/src/node/Puppeteer.ts +++ b/src/node/Puppeteer.ts @@ -39,14 +39,13 @@ export interface PuppeteerLaunchOptions } /** - * Extends the main {@link Puppeteer} class with Node specific behaviour for fetching and - * downloading browsers. + * Extends the main {@link Puppeteer} class with Node specific behaviour for + * fetching and downloading browsers. * * 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`). * * @remarks - * * The most common method to use is {@link PuppeteerNode.launch | launch}, which * 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. * - * @remarks - * * @param options - Set of configurable options to set on the browser. * @returns Promise which resolves to browser instance. */ @@ -125,10 +122,6 @@ export class PuppeteerNode extends Puppeteer { get _productName(): Product | undefined { return this.#productName; } - - /** - * @internal - */ set _productName(name: Product | undefined) { if (this.#productName !== name) { this._changedProduct = true; @@ -137,10 +130,8 @@ export class PuppeteerNode extends Puppeteer { } /** - * Launches puppeteer and launches a browser instance with given arguments - * and options when specified. - * - * @remarks + * Launches puppeteer and launches a browser instance with given arguments and + * options when specified. * * @example * 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, - * but it works best with the version of Chromium it is bundled with. - * There is no guarantee it will work with any other version. - * Use `executablePath` option with extreme caution. - * 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. - * 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. + * @remarks + * **NOTE** Puppeteer can also be used to control the Chrome browser, but it + * works best with the version of Chromium it is bundled with. There is no + * guarantee it will work with any other version. Use `executablePath` option + * with extreme caution. 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. 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. * @returns Promise which resolves to browser instance. @@ -170,13 +168,13 @@ export class PuppeteerNode extends Puppeteer { /** * @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` - * and `PUPPETEER_CHROMIUM_REVISION` environment variables. - * - * @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. + * @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 { 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 - * The product is set by the `PUPPETEER_PRODUCT` environment variable or the `product` - * option in `puppeteer.launch([options])` and defaults to `chrome`. + * The product is set by the `PUPPETEER_PRODUCT` environment variable or the + * `product` option in `puppeteer.launch([options])` and defaults to `chrome`. * Firefox support is experimental. */ get product(): string { @@ -223,7 +222,6 @@ export class PuppeteerNode extends Puppeteer { } /** - * * @param options - Set of configurable options to set on the browser. * @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 - * of the BrowserFetcher. + * @param options - Set of configurable options to specify the settings of the + * BrowserFetcher. * @returns A new BrowserFetcher instance. */ createBrowserFetcher(options: BrowserFetcherOptions): BrowserFetcher { diff --git a/src/node/install.ts b/src/node/install.ts index 4c3e19ed4740e..9480a33470892 100644 --- a/src/node/install.ts +++ b/src/node/install.ts @@ -23,11 +23,17 @@ import {PuppeteerNode} from './Puppeteer.js'; import createHttpsProxyAgent, {HttpsProxyAgentOptions} from 'https-proxy-agent'; import {getProxyForUrl} from 'proxy-from-env'; +/** + * @internal + */ const supportedProducts = { chrome: 'Chromium', firefox: 'Firefox Nightly', } as const; +/** + * @internal + */ function getProduct(input: string): 'chrome' | 'firefox' { if (input !== 'chrome' && input !== 'firefox') { throw new Error(`Unsupported product ${input}`); @@ -35,6 +41,9 @@ function getProduct(input: string): 'chrome' | 'firefox' { return input; } +/** + * @internal + */ export async function downloadBrowser(): Promise { const downloadHost = process.env['PUPPETEER_DOWNLOAD_HOST'] || @@ -209,6 +218,9 @@ export async function downloadBrowser(): Promise { } } +/** + * @internal + */ export function logPolitely(toBeLogged: unknown): void { const logLevel = process.env['npm_config_loglevel'] || ''; const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1; diff --git a/src/puppeteer-core.ts b/src/puppeteer-core.ts index 201eb525c14f4..50da7183450a6 100644 --- a/src/puppeteer-core.ts +++ b/src/puppeteer-core.ts @@ -16,21 +16,19 @@ 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'); export const { - clearCustomQueryHandlers, connect, createBrowserFetcher, - customQueryHandlerNames, defaultArgs, - devices, - errors, executablePath, launch, - networkConditions, - registerCustomQueryHandler, - unregisterCustomQueryHandler, } = puppeteer; export default puppeteer; diff --git a/src/puppeteer.ts b/src/puppeteer.ts index 7443709f08898..21a4a2ca79b46 100644 --- a/src/puppeteer.ts +++ b/src/puppeteer.ts @@ -16,21 +16,22 @@ 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'); export const { - clearCustomQueryHandlers, connect, createBrowserFetcher, - customQueryHandlerNames, defaultArgs, - devices, - errors, executablePath, launch, - networkConditions, - registerCustomQueryHandler, - unregisterCustomQueryHandler, } = puppeteer; export default puppeteer; diff --git a/src/revisions.ts b/src/revisions.ts index 36eb902f2b9de..b3503987a0fa5 100644 --- a/src/revisions.ts +++ b/src/revisions.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @internal + */ export const PUPPETEER_REVISIONS = Object.freeze({ chromium: '1011831', firefox: 'latest', diff --git a/src/templates/version.ts.tmpl b/src/templates/version.ts.tmpl index 18444ac3b5042..73b984d2fff54 100644 --- a/src/templates/version.ts.tmpl +++ b/src/templates/version.ts.tmpl @@ -1 +1,4 @@ +/** + * @internal + */ export const packageVersion = 'PACKAGE_VERSION'; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000000000..fa4ddbec0480a --- /dev/null +++ b/src/types.ts @@ -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'; diff --git a/test/src/oopif.spec.ts b/test/src/oopif.spec.ts index 0582375a7d4b3..f747910df24b7 100644 --- a/test/src/oopif.spec.ts +++ b/test/src/oopif.spec.ts @@ -24,8 +24,8 @@ import { import { Browser, BrowserContext, - Page, -} from '../../lib/cjs/puppeteer/api-docs-entry.js'; +} from '../../lib/cjs/puppeteer/common/Browser.js'; +import {Page} from '../../lib/cjs/puppeteer/common/Page.js'; describeChromeOnly('OOPIF', function () { /* We use a special browser for this test as we need the --site-per-process flag */ diff --git a/utils/export_all.js b/utils/export_all.js new file mode 100644 index 0000000000000..2cbef44f91291 --- /dev/null +++ b/utils/export_all.js @@ -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);