chore(types): type check the rest of the protocol (#2328)

This adds events and commands into generated `protocol.d.ts`.
This commit is contained in:
JoelEinbinder 2018-04-07 17:58:52 -07:00 committed by Andrey Lushnikov
parent 45d97e572a
commit 294f33b75c
9 changed files with 88 additions and 37 deletions

View File

@ -106,7 +106,7 @@ class JSCoverage {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Debugger.scriptParsedPayload} event
*/ */
async _onScriptParsed(event) { async _onScriptParsed(event) {
// Ignore anonymous scripts // Ignore anonymous scripts
@ -193,7 +193,7 @@ class CSSCoverage {
} }
/** /**
* @param {!Object} event * @param {!Protocol.CSS.styleSheetAddedPayload} event
*/ */
async _onStyleSheet(event) { async _onStyleSheet(event) {
const header = event.header; const header = event.header;

View File

@ -80,7 +80,7 @@ class ElementHandle extends JSHandle {
} }
/** /**
* @return {!Promise<?{model: object}>} * @return {!Promise<void|Protocol.DOM.getBoxModelReturnValue>}
*/ */
_getBoxModel() { _getBoxModel() {
return this._client.send('DOM.getBoxModel', { return this._client.send('DOM.getBoxModel', {

View File

@ -33,13 +33,13 @@ class EmulationManager {
const width = viewport.width; const width = viewport.width;
const height = viewport.height; const height = viewport.height;
const deviceScaleFactor = viewport.deviceScaleFactor || 1; const deviceScaleFactor = viewport.deviceScaleFactor || 1;
/** @type {Protocol.Emulation.ScreenOrientation} */
const screenOrientation = viewport.isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }; const screenOrientation = viewport.isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' };
await Promise.all([ await Promise.all([
this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }), this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }),
this._client.send('Emulation.setTouchEmulationEnabled', { this._client.send('Emulation.setTouchEmulationEnabled', {
enabled: viewport.hasTouch || false, enabled: viewport.hasTouch || false
configuration: viewport.isMobile ? 'mobile' : 'desktop'
}) })
]); ]);

View File

@ -61,7 +61,7 @@ class ExecutionContext {
async evaluateHandle(pageFunction, ...args) { async evaluateHandle(pageFunction, ...args) {
if (helper.isString(pageFunction)) { if (helper.isString(pageFunction)) {
const contextId = this._contextId; const contextId = this._contextId;
const expression = pageFunction; const expression = /** @type {string} */ (pageFunction);
const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true}); const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true});
if (exceptionDetails) if (exceptionDetails)
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));

View File

@ -25,7 +25,7 @@ const readFileAsync = helper.promisify(fs.readFile);
class FrameManager extends EventEmitter { class FrameManager extends EventEmitter {
/** /**
* @param {!Puppeteer.CDPSession} client * @param {!Puppeteer.CDPSession} client
* @param {{frame: Object, childFrames: ?Array}} frameTree * @param {!Protocol.Page.FrameTree} frameTree
* @param {!Puppeteer.Page} page * @param {!Puppeteer.Page} page
*/ */
constructor(client, frameTree, page) { constructor(client, frameTree, page) {
@ -34,7 +34,7 @@ class FrameManager extends EventEmitter {
this._page = page; this._page = page;
/** @type {!Map<string, !Frame>} */ /** @type {!Map<string, !Frame>} */
this._frames = new Map(); this._frames = new Map();
/** @type {!Map<string, !ExecutionContext>} */ /** @type {!Map<number, !ExecutionContext>} */
this._contextIdToContext = new Map(); this._contextIdToContext = new Map();
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)); this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId));
@ -49,7 +49,7 @@ class FrameManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Page.lifecycleEventPayload} event
*/ */
_onLifecycleEvent(event) { _onLifecycleEvent(event) {
const frame = this._frames.get(event.frameId); const frame = this._frames.get(event.frameId);
@ -60,7 +60,7 @@ class FrameManager extends EventEmitter {
} }
/** /**
* @param {{frame: Object, childFrames: ?Array}} frameTree * @param {!Protocol.Page.FrameTree} frameTree
*/ */
_handleFrameTree(frameTree) { _handleFrameTree(frameTree) {
if (frameTree.frame.parentId) if (frameTree.frame.parentId)
@ -171,7 +171,7 @@ class FrameManager extends EventEmitter {
} }
/** /**
* @param {string} executionContextId * @param {number} executionContextId
*/ */
_onExecutionContextDestroyed(executionContextId) { _onExecutionContextDestroyed(executionContextId) {
const context = this._contextIdToContext.get(executionContextId); const context = this._contextIdToContext.get(executionContextId);
@ -188,7 +188,7 @@ class FrameManager extends EventEmitter {
} }
/** /**
* @param {string} contextId * @param {number} contextId
* @param {*} remoteObject * @param {*} remoteObject
* @return {!JSHandle} * @return {!JSHandle}
*/ */

View File

@ -126,10 +126,11 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.requestInterceptedPayload} event
*/ */
_onRequestIntercepted(event) { _onRequestIntercepted(event) {
if (event.authChallenge) { if (event.authChallenge) {
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
let response = 'Default'; let response = 'Default';
if (this._attemptedAuthentications.has(event.interceptionId)) { if (this._attemptedAuthentications.has(event.interceptionId)) {
response = 'CancelAuth'; response = 'CancelAuth';
@ -170,7 +171,7 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.requestServedFromCachePayload} event
*/ */
_onRequestServedFromCache(event) { _onRequestServedFromCache(event) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
@ -219,7 +220,7 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.requestWillBeSentPayload} event
*/ */
_onRequestWillBeSent(event) { _onRequestWillBeSent(event) {
if (this._protocolRequestInterceptionEnabled) { if (this._protocolRequestInterceptionEnabled) {
@ -251,7 +252,7 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.responseReceivedPayload} event
*/ */
_onResponseReceived(event) { _onResponseReceived(event) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
@ -265,7 +266,7 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.loadingFinishedPayload} event
*/ */
_onLoadingFinished(event) { _onLoadingFinished(event) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
@ -281,7 +282,7 @@ class NetworkManager extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Network.loadingFailedPayload} event
*/ */
_onLoadingFailed(event) { _onLoadingFailed(event) {
const request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);

View File

@ -63,7 +63,7 @@ class Page extends EventEmitter {
/** /**
* @param {!Puppeteer.CDPSession} client * @param {!Puppeteer.CDPSession} client
* @param {!Puppeteer.Target} target * @param {!Puppeteer.Target} target
* @param {{frame: Object, childFrames: ?Array}} frameTree * @param {!Protocol.Page.FrameTree} frameTree
* @param {boolean} ignoreHTTPSErrors * @param {boolean} ignoreHTTPSErrors
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue * @param {!Puppeteer.TaskQueue} screenshotTaskQueue
*/ */
@ -182,7 +182,7 @@ class Page extends EventEmitter {
} }
/** /**
* @param {!Object} event * @param {!Protocol.Security.certificateErrorPayload} event
*/ */
_onCertificateError(event) { _onCertificateError(event) {
if (!this._ignoreHTTPSErrors) if (!this._ignoreHTTPSErrors)
@ -404,7 +404,7 @@ class Page extends EventEmitter {
} }
/** /**
* @param {!Object} exceptionDetails * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
*/ */
_handleException(exceptionDetails) { _handleException(exceptionDetails) {
const message = helper.getExceptionMessage(exceptionDetails); const message = helper.getExceptionMessage(exceptionDetails);
@ -708,7 +708,7 @@ class Page extends EventEmitter {
} }
/** /**
* @param {string} format * @param {"png"|"jpeg"} format
* @param {!Object=} options * @param {!Object=} options
* @return {!Promise<!Buffer>} * @return {!Promise<!Buffer>}
*/ */
@ -728,6 +728,7 @@ class Page extends EventEmitter {
const mobile = this._viewport.isMobile || false; const mobile = this._viewport.isMobile || false;
const deviceScaleFactor = this._viewport.deviceScaleFactor || 1; const deviceScaleFactor = this._viewport.deviceScaleFactor || 1;
const landscape = this._viewport.isLandscape || false; const landscape = this._viewport.isLandscape || false;
/** @type {!Protocol.Emulation.ScreenOrientation} */
const screenOrientation = landscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }; const screenOrientation = landscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' };
await this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }); await this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation });
} }
@ -1024,7 +1025,7 @@ Page.Events = {
/** /**
* @typedef {Object} Network.CookieParam * @typedef {Object} Network.CookieParam
* @property {string} name * @property {string} name
* @property {string=} value * @property {string} value
* @property {string=} url * @property {string=} url
* @property {string=} domain * @property {string=} domain
* @property {string=} path * @property {string=} path

5
lib/externs.d.ts vendored
View File

@ -12,7 +12,10 @@ import * as child_process from 'child_process';
declare global { declare global {
module Puppeteer { module Puppeteer {
export class Connection extends RealConnection {} export class Connection extends RealConnection {}
export class CDPSession extends RealCDPSession {} export class CDPSession extends RealCDPSession {
on<T extends keyof Protocol.Events>(event: T, listener: (arg: Protocol.Events[T]) => void): this;
send<T extends keyof Protocol.CommandParameters>(message: T, parameters?: Protocol.CommandParameters[T]): Promise<Protocol.CommandReturnValues[T]>;
}
export class Mouse extends RealMouse {} export class Mouse extends RealMouse {}
export class Keyboard extends RealKeyboard {} export class Keyboard extends RealKeyboard {}
export class Touchscreen extends RealTouchscreen {} export class Touchscreen extends RealTouchscreen {}

View File

@ -1,3 +1,4 @@
// @ts-check
const puppeteer = require('../..'); const puppeteer = require('../..');
puppeteer.launch({ puppeteer.launch({
pipe: false, pipe: false,
@ -11,28 +12,59 @@ puppeteer.launch({
await browser.close(); await browser.close();
const output = `// This is generated from /utils/protocol-types-generator/index.js const output = `// This is generated from /utils/protocol-types-generator/index.js
declare global { declare global {
module Protocol { module Protocol {${json.domains.map(domain => `${domain.description ? `
${json.domains.map(domain => `${domain.description ? `
/** /**
* ${domain.description} * ${domain.description}
*/` : ''} */` : ''}
export module ${domain.domain} { export module ${domain.domain} {${(domain.types || []).map(type => `${type.description ? `
${(domain.types || []).map(type => `${type.description ? `
/** /**
* ${type.description} * ${type.description}
*/` : ''}${type.properties ? ` */` : ''}${type.properties ? `
export interface ${type.id} { export interface ${type.id} {${(type.properties || []).map(property => `${property.description ? `
${(type.properties || []).map(property => `${property.description ? `
/** /**
* ${property.description} * ${property.description}
*/` : ''} */` : ''}
${property.name}${property.optional ? '?' : ''}: ${typeOfProperty(property)}; ${property.name}${property.optional ? '?' : ''}: ${typeOfProperty(property)};`).join(``)}
`).join(``)}
}` : ` }` : `
export type ${type.id} = ${typeOfProperty(type)};`} export type ${type.id} = ${typeOfProperty(type)};`}`).join('')}
`).join('')} ${(domain.events || []).map(event => `${event.description ? `
/**
* ${event.description}
*/` : ''}${event.parameters ? `
export type ${event.name}Payload = {${event.parameters.map(parameter => `${parameter.description ? `
/**
* ${parameter.description}
*/` : ''}
${parameter.name}${parameter.optional ? '?' : ''}: ${typeOfProperty(parameter)};`).join(``)}
}` : `
export type ${event.name}Payload = void;`}`).join('')}
${(domain.commands || []).map(command => `${command.description ? `
/**
* ${command.description}
*/` : ''}
export type ${command.name}Parameters = {${(command.parameters || []).map(parameter => `${parameter.description ? `
/**
* ${parameter.description}
*/` : ''}
${parameter.name}${parameter.optional ? '?' : ''}: ${typeOfProperty(parameter)};`).join(``)}
}
export type ${command.name}ReturnValue = {${(command.returns || []).map(retVal => `${retVal.description ? `
/**
* ${retVal.description}
*/` : ''}
${retVal.name}${retVal.optional ? '?' : ''}: ${typeOfProperty(retVal)};`).join(``)}
}`).join('')}
} }
`).join('')} `).join('')}
export interface Events {${json.domains.map(domain => (domain.events || []).map(event => `
"${domain.domain}.${event.name}": ${domain.domain}.${event.name}Payload;`).join('')).join('')}
}
export interface CommandParameters {${json.domains.map(domain => (domain.commands || []).map(command => `
"${domain.domain}.${command.name}": ${domain.domain}.${command.name}Parameters;`).join('')).join('')}
}
export interface CommandReturnValues {${json.domains.map(domain => (domain.commands || []).map(command => `
"${domain.domain}.${command.name}": ${domain.domain}.${command.name}ReturnValue;`).join('')).join('')}
}
} }
} }
// empty export to keep file a module // empty export to keep file a module
@ -41,12 +73,26 @@ export {}
require('fs').writeFileSync(require('path').join(__dirname, '..', '..', 'lib', 'protocol.d.ts'), output); require('fs').writeFileSync(require('path').join(__dirname, '..', '..', 'lib', 'protocol.d.ts'), output);
}); });
function typeOfProperty(property) {
if (property.$ref) return property.$ref; /**
* @typedef {Object} Property
* @property {string=} $ref
* @property {!Array=} enum
* @property {string=} type
* @property {!Property=} items
* @property {string=} description
*/
/**
* @param {!Property} property
* @param {string=} domain
*/
function typeOfProperty(property, domain) {
if (property.$ref) return property.$ref.includes('.') || !domain ? property.$ref : domain + '.' + property.$ref;
if (property.enum) return property.enum.map(value => JSON.stringify(value)).join('|'); if (property.enum) return property.enum.map(value => JSON.stringify(value)).join('|');
switch (property.type) { switch (property.type) {
case 'array': case 'array':
return typeOfProperty(property.items) + '[]'; return typeOfProperty(property.items, domain) + '[]';
case 'integer': case 'integer':
return 'number'; return 'number';
} }