chore: migrate src/Page.js to TypeScript (#5809)

* chore: migrate src/Page.js to TypeScript

The final one! This is a huge file and needs to be split up and tidied,
but for now I've left all the definitions in place and converted types
accordingly.

There's some additional tidying we can do now every `src` file is TS,
but I'll leave that for another PR to avoid this one getting any bigger.

Co-authored-by: Mathias Bynens <mathias@qiwi.be>
This commit is contained in:
Jack Franklin 2020-05-05 13:53:22 +01:00 committed by GitHub
parent eed7d94a2b
commit de4f08dc52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 353 additions and 688 deletions

View File

@ -20,6 +20,7 @@ import * as EventEmitter from 'events';
import {TaskQueue} from './TaskQueue';
import {Events} from './Events';
import {Connection} from './Connection';
import {Page} from './Page';
import {ChildProcess} from 'child_process';
type BrowserCloseCallback = () => Promise<void> | void;
@ -137,11 +138,11 @@ export class Browser extends EventEmitter {
return this._connection.url();
}
async newPage(): Promise<Puppeteer.Page> {
async newPage(): Promise<Page> {
return this._defaultContext.newPage();
}
async _createPageInContext(contextId?: string): Promise<Puppeteer.Page> {
async _createPageInContext(contextId?: string): Promise<Page> {
const {targetId} = await this._connection.send('Target.createTarget', {url: 'about:blank', browserContextId: contextId || undefined});
const target = await this._targets.get(targetId);
assert(await target._initializedPromise, 'Failed to create target for page');
@ -188,10 +189,7 @@ export class Browser extends EventEmitter {
}
}
/**
* @return {!Promise<!Array<!Puppeteer.Page>>}
*/
async pages(): Promise<Puppeteer.Page[]> {
async pages(): Promise<Page[]> {
const contextPages = await Promise.all(this.browserContexts().map(context => context.pages()));
// Flatten array.
return contextPages.reduce((acc, x) => acc.concat(x), []);
@ -245,7 +243,7 @@ export class BrowserContext extends EventEmitter {
return this._browser.waitForTarget(target => target.browserContext() === this && predicate(target), options);
}
async pages(): Promise<Puppeteer.Page[]> {
async pages(): Promise<Page[]> {
const pages = await Promise.all(
this.targets()
.filter(target => target.type() === 'page')
@ -292,7 +290,7 @@ export class BrowserContext extends EventEmitter {
await this._connection.send('Browser.resetPermissions', {browserContextId: this._id || undefined});
}
newPage(): Promise<Puppeteer.Page> {
newPage(): Promise<Page> {
return this._browser._createPageInContext(this._id);
}

View File

@ -17,14 +17,17 @@
import {assert} from './helper';
import {CDPSession} from './Connection';
enum DialogType {
/* TODO(jacktfranklin): protocol.d.ts defines this
* so let's ditch this and avoid the duplication
*/
export enum DialogType {
Alert = 'alert',
BeforeUnload = 'beforeunload',
Confirm = 'confirm',
Prompt = 'prompt'
}
class Dialog {
export class Dialog {
static Type = DialogType;
private _client: CDPSession;
@ -69,5 +72,3 @@ class Dialog {
});
}
}
export = {Dialog};

View File

@ -25,12 +25,13 @@ import {TimeoutSettings} from './TimeoutSettings';
import {CDPSession} from './Connection';
import {JSHandle, ElementHandle} from './JSHandle';
import {MouseButtonInput} from './Input';
import {Page} from './Page';
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
export class FrameManager extends EventEmitter {
_client: CDPSession;
_page: Puppeteer.Page;
_page: Page;
_networkManager: NetworkManager;
_timeoutSettings: TimeoutSettings;
_frames = new Map<string, Frame>();
@ -38,7 +39,7 @@ export class FrameManager extends EventEmitter {
_isolatedWorlds = new Set<string>();
_mainFrame: Frame;
constructor(client: CDPSession, page: Puppeteer.Page, ignoreHTTPSErrors: boolean, timeoutSettings: TimeoutSettings) {
constructor(client: CDPSession, page: Page, ignoreHTTPSErrors: boolean, timeoutSettings: TimeoutSettings) {
super();
this._client = client;
this._page = page;
@ -155,7 +156,7 @@ export class FrameManager extends EventEmitter {
this._handleFrameTree(child);
}
page(): Puppeteer.Page {
page(): Page {
return this._page;
}

View File

@ -16,6 +16,7 @@
import {helper, assert, debugError} from './helper';
import {ExecutionContext} from './ExecutionContext';
import {Page} from './Page';
import {CDPSession} from './Connection';
import {KeyInput} from './USKeyboardLayout';
import {FrameManager, Frame} from './FrameManager';
@ -124,16 +125,9 @@ export class JSHandle {
}
export class ElementHandle extends JSHandle {
_page: Puppeteer.Page;
_page: Page;
_frameManager: FrameManager;
/**
* @param {!ExecutionContext} context
* @param {!CDPSession} client
* @param {!Protocol.Runtime.RemoteObject} remoteObject
* @param {!Puppeteer.Page} page
* @param {!FrameManager} frameManager
*/
constructor(context: ExecutionContext, client: CDPSession, remoteObject: Protocol.Runtime.RemoteObject, page: Puppeteer.Page, frameManager: FrameManager) {
constructor(context: ExecutionContext, client: CDPSession, remoteObject: Protocol.Runtime.RemoteObject, page: Page, frameManager: FrameManager) {
super(context, client, remoteObject);
this._client = client;
this._remoteObject = remoteObject;
@ -231,12 +225,6 @@ export class ElementHandle extends JSHandle {
];
}
/**
* @param {!Array<{x: number, y: number}>} quad
* @param {number} width
* @param {number} height
* @return {!Array<{x: number, y: number}>}
*/
_intersectQuadWithViewport(quad: Array<{x: number; y: number}>, width: number, height: number): Array<{x: number; y: number}> {
return quad.map(point => ({
x: Math.min(Math.max(point.x, 0), width),
@ -256,10 +244,6 @@ export class ElementHandle extends JSHandle {
await this._page.mouse.click(x, y, options);
}
/**
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(...values: string[]): Promise<string[]> {
for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
@ -439,10 +423,6 @@ export class ElementHandle extends JSHandle {
return null;
}
/**
* @param {string} selector
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $$(selector: string): Promise<ElementHandle[]> {
const defaultHandler = (element: Element, selector: string) => element.querySelectorAll(selector);
const {updatedSelector, queryHandler} = getQueryHandlerAndSelector(selector, defaultHandler);

View File

@ -19,7 +19,7 @@ import {Events} from './Events';
import {CDPSession} from './Connection';
import {FrameManager, Frame} from './FrameManager';
interface Credentials {
export interface Credentials {
username: string;
password: string;
}

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ export class Target {
_ignoreHTTPSErrors: boolean;
_defaultViewport?: Puppeteer.Viewport;
_screenshotTaskQueue: TaskQueue;
_pagePromise?: Promise<Puppeteer.Page>;
_pagePromise?: Promise<Page>;
_workerPromise?: Promise<PuppeteerWorker>;
_initializedPromise: Promise<boolean>;
_initializedCallback: (x: boolean) => void;
@ -72,7 +72,7 @@ export class Target {
return this._sessionFactory();
}
async page(): Promise<Puppeteer.Page | null> {
async page(): Promise<Page | null> {
if ((this._targetInfo.type === 'page' || this._targetInfo.type === 'background_page') && !this._pagePromise) {
this._pagePromise = this._sessionFactory()
.then(client => Page.create(client, this, this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue));

7
src/externs.d.ts vendored
View File

@ -1,14 +1,7 @@
import {Page as RealPage} from './Page.js';
import * as child_process from 'child_process';
declare global {
module Puppeteer {
export class Page extends RealPage { }
/* TODO(jacktfranklin@): once DOMWorld, Page, and FrameManager are in TS
* we can remove this and instead use the type defined in LifeCycleWatcher
*/
export type PuppeteerLifeCycleEvent = 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
export interface ConnectionTransport {
send(string);
close();

View File

@ -359,6 +359,46 @@ function compareDocumentations(actual, expected) {
actualName: 'Object',
expectedName: 'BrowserFetcherOptions'
}],
['Method Page.authenticate() credentials', {
actualName: 'Object',
expectedName: 'Credentials'
}],
['Method Page.emulateMediaFeatures() features', {
actualName: 'Array<Object>',
expectedName: 'Array<MediaFeature>'
}],
['Method Page.goBack() options', {
actualName: 'Object',
expectedName: 'WaitForOptions'
}],
['Method Page.goForward() options', {
actualName: 'Object',
expectedName: 'WaitForOptions'
}],
['Method Page.reload() options', {
actualName: 'Object',
expectedName: 'WaitForOptions'
}],
['Method Page.waitForNavigation() options', {
actualName: 'Object',
expectedName: 'WaitForOptions'
}],
['Method Page.pdf() options', {
actualName: 'Object',
expectedName: 'PDFOptions'
}],
['Method Page.screenshot() options', {
actualName: 'Object',
expectedName: 'ScreenshotOptions'
}],
['Method Page.setContent() options', {
actualName: 'Object',
expectedName: 'WaitForOptions'
}],
['Method Page.setCookie() ...cookies', {
actualName: '...Object',
expectedName: '...CookieParam'
}],
]);
const expectedForSource = expectedNamingMismatches.get(source);