mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: use devtools-protocol package (#6172)
* chore: Use devtools-protocol package Rather than maintain our own protocol we can instead use the devtools-protocol package and pin it to the version of Chromium that Puppeteer is shipping with. The only changes are naming changes between the bespoke protocol that Puppeteer created and the devtools-protocol one.
This commit is contained in:
parent
f666be3f5f
commit
31309b0e20
@ -6,8 +6,6 @@ node6/*
|
|||||||
node6-test/*
|
node6-test/*
|
||||||
experimental/
|
experimental/
|
||||||
lib/
|
lib/
|
||||||
src/externs.d.ts
|
|
||||||
src/protocol.d.ts
|
|
||||||
/index.d.ts
|
/index.d.ts
|
||||||
# We ignore this file because it uses ES imports which we don't yet use
|
# We ignore this file because it uses ES imports which we don't yet use
|
||||||
# in the Puppeteer src, so it trips up the ESLint-TypeScript parser.
|
# in the Puppeteer src, so it trips up the ESLint-TypeScript parser.
|
||||||
|
@ -63,9 +63,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
- CHROMIUM=true
|
- CHROMIUM=true
|
||||||
script:
|
script:
|
||||||
- npm run compare-protocol-d-ts
|
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm run ensure-new-docs-up-to-date
|
- npm run ensure-new-docs-up-to-date
|
||||||
|
- npm run ensure-correct-devtools-protocol-revision
|
||||||
|
|
||||||
# This bot runs separately as it changes package.json to test puppeteer-core
|
# This bot runs separately as it changes package.json to test puppeteer-core
|
||||||
# and we don't want that leaking into other bots and causing issues.
|
# and we don't want that leaking into other bots and causing issues.
|
||||||
|
@ -331,7 +331,7 @@
|
|||||||
* [target.worker()](#targetworker)
|
* [target.worker()](#targetworker)
|
||||||
- [class: CDPSession](#class-cdpsession)
|
- [class: CDPSession](#class-cdpsession)
|
||||||
* [cdpSession.detach()](#cdpsessiondetach)
|
* [cdpSession.detach()](#cdpsessiondetach)
|
||||||
* [cdpSession.send(method[, params])](#cdpsessionsendmethod-params)
|
* [cdpSession.send(method[, ...paramArgs])](#cdpsessionsendmethod-paramargs)
|
||||||
- [class: Coverage](#class-coverage)
|
- [class: Coverage](#class-coverage)
|
||||||
* [coverage.startCSSCoverage([options])](#coveragestartcsscoverageoptions)
|
* [coverage.startCSSCoverage([options])](#coveragestartcsscoverageoptions)
|
||||||
* [coverage.startJSCoverage([options])](#coveragestartjscoverageoptions)
|
* [coverage.startJSCoverage([options])](#coveragestartjscoverageoptions)
|
||||||
@ -3946,9 +3946,9 @@ await client.send('Animation.setPlaybackRate', {
|
|||||||
Detaches the cdpSession from the target. Once detached, the cdpSession object won't emit any events and can't be used
|
Detaches the cdpSession from the target. Once detached, the cdpSession object won't emit any events and can't be used
|
||||||
to send messages.
|
to send messages.
|
||||||
|
|
||||||
#### cdpSession.send(method[, params])
|
#### cdpSession.send(method[, ...paramArgs])
|
||||||
- `method` <[string]> protocol method name
|
- `method` <[string]> protocol method name
|
||||||
- `params` <[Object]> Optional method parameters
|
- `...paramArgs` <[Object]> Optional method parameters
|
||||||
- returns: <[Promise]<[Object]>>
|
- returns: <[Promise]<[Object]>>
|
||||||
|
|
||||||
### class: Coverage
|
### class: Coverage
|
||||||
|
@ -41,5 +41,5 @@ await client.send('Animation.setPlaybackRate', {
|
|||||||
| Method | Modifiers | Description |
|
| Method | Modifiers | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [detach()](./puppeteer.cdpsession.detach.md) | | Detaches the cdpSession from the target. Once detached, the cdpSession object won't emit any events and can't be used to send messages. |
|
| [detach()](./puppeteer.cdpsession.detach.md) | | Detaches the cdpSession from the target. Once detached, the cdpSession object won't emit any events and can't be used to send messages. |
|
||||||
| [send(method, params)](./puppeteer.cdpsession.send.md) | | |
|
| [send(method, paramArgs)](./puppeteer.cdpsession.send.md) | | |
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
send<T extends keyof Protocol.CommandParameters>(method: T, params?: Protocol.CommandParameters[T]): Promise<Protocol.CommandReturnValues[T]>;
|
send<T extends keyof ProtocolMapping.Commands>(method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType']): Promise<ProtocolMapping.Commands[T]['returnType']>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
@ -15,9 +15,9 @@ send<T extends keyof Protocol.CommandParameters>(method: T, params?: Protocol.Co
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| method | T | |
|
| method | T | |
|
||||||
| params | Protocol.CommandParameters\[T\] | |
|
| paramArgs | ProtocolMapping.Commands\[T\]\['paramsType'\] | |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
Promise<Protocol.CommandReturnValues\[T\]>
|
Promise<ProtocolMapping.Commands\[T\]\['returnType'\]>
|
||||||
|
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
deleteCookie(...cookies: Protocol.Network.deleteCookiesParameters[]): Promise<void>;
|
deleteCookie(...cookies: Protocol.Network.DeleteCookiesRequest[]): Promise<void>;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| cookies | Protocol.Network.deleteCookiesParameters\[\] | |
|
| cookies | Protocol.Network.DeleteCookiesRequest\[\] | |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
|
10
package.json
10
package.json
@ -24,16 +24,15 @@
|
|||||||
"doc": "node utils/doclint/cli.js",
|
"doc": "node utils/doclint/cli.js",
|
||||||
"clean-lib": "rm -rf lib",
|
"clean-lib": "rm -rf lib",
|
||||||
"tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm",
|
"tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm",
|
||||||
"tsc-cjs": "tsc -p . && cp src/protocol.d.ts lib/cjs",
|
"tsc-cjs": "tsc -p .",
|
||||||
"tsc-esm": "tsc --build tsconfig-esm.json && cp src/protocol.d.ts lib/esm",
|
"tsc-esm": "tsc --build tsconfig-esm.json",
|
||||||
"typecheck": "tsc -p . --noEmit",
|
"typecheck": "tsc -p . --noEmit",
|
||||||
"apply-next-version": "node utils/apply_next_version.js",
|
"apply-next-version": "node utils/apply_next_version.js",
|
||||||
"update-protocol-d-ts": "node utils/protocol-types-generator update",
|
|
||||||
"compare-protocol-d-ts": "node utils/protocol-types-generator compare",
|
|
||||||
"test-install": "scripts/test-install.sh",
|
"test-install": "scripts/test-install.sh",
|
||||||
"generate-docs": "npm run tsc && api-extractor run --local --verbose && api-documenter markdown -i temp -o new-docs",
|
"generate-docs": "npm run tsc && api-extractor run --local --verbose && api-documenter markdown -i temp -o new-docs",
|
||||||
"ensure-new-docs-up-to-date": "npm run generate-docs && exit `git status --porcelain | head -255 | wc -l`",
|
"ensure-new-docs-up-to-date": "npm run generate-docs && exit `git status --porcelain | head -255 | wc -l`",
|
||||||
"generate-dependency-graph": "echo 'Requires graphviz installed locally!' && depcruise --exclude 'api.ts' --do-not-follow '^node_modules' --output-type dot src/index.ts | dot -T png > dependency-chart.png"
|
"generate-dependency-graph": "echo 'Requires graphviz installed locally!' && depcruise --exclude 'api.ts' --do-not-follow '^node_modules' --output-type dot src/index.ts | dot -T png > dependency-chart.png",
|
||||||
|
"ensure-correct-devtools-protocol-revision": "ts-node scripts/ensure-correct-devtools-protocol-package"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"lib/",
|
"lib/",
|
||||||
@ -46,6 +45,7 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
|
"devtools-protocol": "0.0.754670",
|
||||||
"extract-zip": "^2.0.0",
|
"extract-zip": "^2.0.0",
|
||||||
"https-proxy-agent": "^4.0.0",
|
"https-proxy-agent": "^4.0.0",
|
||||||
"mime": "^2.0.3",
|
"mime": "^2.0.3",
|
||||||
|
83
scripts/ensure-correct-devtools-protocol-package.ts
Normal file
83
scripts/ensure-correct-devtools-protocol-package.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script ensures that the pinned version of devtools-protocol in
|
||||||
|
* package.json is the right version for the current revision of Chromium that
|
||||||
|
* Puppeteer ships with.
|
||||||
|
*
|
||||||
|
* The devtools-protocol package publisher runs every hour and checks if there
|
||||||
|
* are protocol changes. If there are, it will be versioned with the revision
|
||||||
|
* number of the commit that last changed the .pdl files.
|
||||||
|
*
|
||||||
|
* Chromium branches/releases are figured out at a later point in time, so it's
|
||||||
|
* not true that each Chromium revision will have an exact matching revision
|
||||||
|
* version of devtools-protocol. To ensure we're using a devtools-protocol that
|
||||||
|
* is aligned with our revision, we want to find the largest package number
|
||||||
|
* that's <= the revision that Puppeteer is using.
|
||||||
|
*
|
||||||
|
* This script uses npm's `view` function to list all versions in a range and
|
||||||
|
* find the one closest to our Chromium revision.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { PUPPETEER_REVISIONS } from '../src/revisions';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
|
import packageJson from '../package.json';
|
||||||
|
|
||||||
|
const currentProtocolPackageInstalledVersion =
|
||||||
|
packageJson.dependencies['devtools-protocol'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the devtools-protocol version is pinned.
|
||||||
|
*/
|
||||||
|
if (/^[^0-9]/.test(currentProtocolPackageInstalledVersion)) {
|
||||||
|
console.log(
|
||||||
|
`ERROR: devtools-protocol package is not pinned to a specific version.\n`
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the right revision for our Chromium revision
|
||||||
|
|
||||||
|
const command = `npm view "devtools-protocol@<=0.0.${PUPPETEER_REVISIONS.chromium}" version | tail -1`;
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'Checking npm for devtools-protocol revisions:\n',
|
||||||
|
`'${command}'`,
|
||||||
|
'\n'
|
||||||
|
);
|
||||||
|
|
||||||
|
const output = execSync(command, {
|
||||||
|
encoding: 'utf8',
|
||||||
|
});
|
||||||
|
|
||||||
|
const bestRevisionFromNpm = output.split(' ')[1].replace(/'|\n/g, '');
|
||||||
|
|
||||||
|
if (currentProtocolPackageInstalledVersion !== bestRevisionFromNpm) {
|
||||||
|
console.log(`ERROR: bad devtools-protocol revision detected:
|
||||||
|
|
||||||
|
Current Puppeteer Chromium revision: ${PUPPETEER_REVISIONS.chromium}
|
||||||
|
Current devtools-protocol version in package.json: ${currentProtocolPackageInstalledVersion}
|
||||||
|
Expected devtools-protocol version: ${bestRevisionFromNpm}`);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Correct devtools-protocol version found (${bestRevisionFromNpm}).`
|
||||||
|
);
|
||||||
|
process.exit(0);
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { ElementHandle } from './JSHandle';
|
import { ElementHandle } from './JSHandle';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Node and the properties of it that are relevant to Accessibility.
|
* Represents a Node and the properties of it that are relevant to Accessibility.
|
||||||
|
@ -18,8 +18,8 @@ import { assert } from './assert';
|
|||||||
import { helper } from './helper';
|
import { helper } from './helper';
|
||||||
import { Target } from './Target';
|
import { Target } from './Target';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
import Protocol from '../protocol';
|
|
||||||
import { Connection, ConnectionEmittedEvents } from './Connection';
|
import { Connection, ConnectionEmittedEvents } from './Connection';
|
||||||
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { Page } from './Page';
|
import { Page } from './Page';
|
||||||
import { ChildProcess } from 'child_process';
|
import { ChildProcess } from 'child_process';
|
||||||
import { Viewport } from './PuppeteerViewport';
|
import { Viewport } from './PuppeteerViewport';
|
||||||
@ -272,7 +272,7 @@ export class Browser extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _targetCreated(
|
private async _targetCreated(
|
||||||
event: Protocol.Target.targetCreatedPayload
|
event: Protocol.Target.TargetCreatedEvent
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const targetInfo = event.targetInfo;
|
const targetInfo = event.targetInfo;
|
||||||
const { browserContextId } = targetInfo;
|
const { browserContextId } = targetInfo;
|
||||||
@ -314,7 +314,7 @@ export class Browser extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _targetInfoChanged(
|
private _targetInfoChanged(
|
||||||
event: Protocol.Target.targetInfoChangedPayload
|
event: Protocol.Target.TargetInfoChangedEvent
|
||||||
): void {
|
): void {
|
||||||
const target = this._targets.get(event.targetInfo.targetId);
|
const target = this._targets.get(event.targetInfo.targetId);
|
||||||
assert(target, 'target should exist before targetInfoChanged');
|
assert(target, 'target should exist before targetInfoChanged');
|
||||||
@ -500,7 +500,7 @@ export class Browser extends EventEmitter {
|
|||||||
return !this._connection._closed;
|
return !this._connection._closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getVersion(): Promise<Protocol.Browser.getVersionReturnValue> {
|
private _getVersion(): Promise<Protocol.Browser.GetVersionResponse> {
|
||||||
return this._connection.send('Browser.getVersion');
|
return this._connection.send('Browser.getVersion');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ import { debug } from './Debug';
|
|||||||
const debugProtocolSend = debug('puppeteer:protocol:SEND ►');
|
const debugProtocolSend = debug('puppeteer:protocol:SEND ►');
|
||||||
const debugProtocolReceive = debug('puppeteer:protocol:RECV ◀');
|
const debugProtocolReceive = debug('puppeteer:protocol:RECV ◀');
|
||||||
|
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
import { ProtocolMapping } from 'devtools-protocol/types/protocol-mapping';
|
||||||
import { ConnectionTransport } from './ConnectionTransport';
|
import { ConnectionTransport } from './ConnectionTransport';
|
||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
|
|
||||||
@ -77,10 +78,17 @@ export class Connection extends EventEmitter {
|
|||||||
return this._url;
|
return this._url;
|
||||||
}
|
}
|
||||||
|
|
||||||
send<T extends keyof Protocol.CommandParameters>(
|
send<T extends keyof ProtocolMapping.Commands>(
|
||||||
method: T,
|
method: T,
|
||||||
params?: Protocol.CommandParameters[T]
|
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
||||||
): Promise<Protocol.CommandReturnValues[T]> {
|
): Promise<ProtocolMapping.Commands[T]['returnType']> {
|
||||||
|
// There is only ever 1 param arg passed, but the Protocol defines it as an
|
||||||
|
// array of 0 or 1 items See this comment:
|
||||||
|
// https://github.com/ChromeDevTools/devtools-protocol/pull/113#issuecomment-412603285
|
||||||
|
// which explains why the protocol defines the params this way for better
|
||||||
|
// type-inference.
|
||||||
|
// So now we check if there are any params or not and deal with them accordingly.
|
||||||
|
const params = paramArgs.length ? paramArgs[0] : undefined;
|
||||||
const id = this._rawSend({ method, params });
|
const id = this._rawSend({ method, params });
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this._callbacks.set(id, { resolve, reject, error: new Error(), method });
|
this._callbacks.set(id, { resolve, reject, error: new Error(), method });
|
||||||
@ -232,10 +240,10 @@ export class CDPSession extends EventEmitter {
|
|||||||
this._sessionId = sessionId;
|
this._sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
send<T extends keyof Protocol.CommandParameters>(
|
send<T extends keyof ProtocolMapping.Commands>(
|
||||||
method: T,
|
method: T,
|
||||||
params?: Protocol.CommandParameters[T]
|
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
||||||
): Promise<Protocol.CommandReturnValues[T]> {
|
): Promise<ProtocolMapping.Commands[T]['returnType']> {
|
||||||
if (!this._connection)
|
if (!this._connection)
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
@ -243,6 +251,9 @@ export class CDPSession extends EventEmitter {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// See the comment in Connection#send explaining why we do this.
|
||||||
|
const params = paramArgs.length ? paramArgs[0] : undefined;
|
||||||
|
|
||||||
const id = this._connection._rawSend({
|
const id = this._connection._rawSend({
|
||||||
sessionId: this._sessionId,
|
sessionId: this._sessionId,
|
||||||
method,
|
method,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { helper, debugError, PuppeteerEventListener } from './helper';
|
import { helper, debugError, PuppeteerEventListener } from './helper';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
|
|
||||||
import { EVALUATION_SCRIPT_URL } from './ExecutionContext';
|
import { EVALUATION_SCRIPT_URL } from './ExecutionContext';
|
||||||
@ -223,7 +223,7 @@ class JSCoverage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _onScriptParsed(
|
async _onScriptParsed(
|
||||||
event: Protocol.Debugger.scriptParsedPayload
|
event: Protocol.Debugger.ScriptParsedEvent
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Ignore puppeteer-injected scripts
|
// Ignore puppeteer-injected scripts
|
||||||
if (event.url === EVALUATION_SCRIPT_URL) return;
|
if (event.url === EVALUATION_SCRIPT_URL) return;
|
||||||
@ -246,10 +246,10 @@ class JSCoverage {
|
|||||||
this._enabled = false;
|
this._enabled = false;
|
||||||
|
|
||||||
const result = await Promise.all<
|
const result = await Promise.all<
|
||||||
Protocol.Profiler.takePreciseCoverageReturnValue,
|
Protocol.Profiler.TakePreciseCoverageResponse,
|
||||||
Protocol.Profiler.stopPreciseCoverageReturnValue,
|
void,
|
||||||
Protocol.Profiler.disableReturnValue,
|
void,
|
||||||
Protocol.Debugger.disableReturnValue
|
void
|
||||||
>([
|
>([
|
||||||
this._client.send('Profiler.takePreciseCoverage'),
|
this._client.send('Profiler.takePreciseCoverage'),
|
||||||
this._client.send('Profiler.stopPreciseCoverage'),
|
this._client.send('Profiler.stopPreciseCoverage'),
|
||||||
@ -322,9 +322,7 @@ class CSSCoverage {
|
|||||||
this._stylesheetSources.clear();
|
this._stylesheetSources.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onStyleSheet(
|
async _onStyleSheet(event: Protocol.CSS.StyleSheetAddedEvent): Promise<void> {
|
||||||
event: Protocol.CSS.styleSheetAddedPayload
|
|
||||||
): Promise<void> {
|
|
||||||
const header = event.header;
|
const header = event.header;
|
||||||
// Ignore anonymous scripts
|
// Ignore anonymous scripts
|
||||||
if (!header.sourceURL) return;
|
if (!header.sourceURL) return;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog instances are dispatched by the {@link Page} via the `dialog` event.
|
* Dialog instances are dispatched by the {@link Page} via the `dialog` event.
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { Viewport } from './PuppeteerViewport';
|
import { Viewport } from './PuppeteerViewport';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
export class EmulationManager {
|
export class EmulationManager {
|
||||||
_client: CDPSession;
|
_client: CDPSession;
|
||||||
|
@ -20,7 +20,7 @@ import { createJSHandle, JSHandle, ElementHandle } from './JSHandle';
|
|||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { DOMWorld } from './DOMWorld';
|
import { DOMWorld } from './DOMWorld';
|
||||||
import { Frame } from './FrameManager';
|
import { Frame } from './FrameManager';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
||||||
|
|
||||||
export const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
|
export const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
|
||||||
@ -301,7 +301,7 @@ export class ExecutionContext {
|
|||||||
return { value: arg };
|
return { value: arg };
|
||||||
}
|
}
|
||||||
|
|
||||||
function rewriteError(error: Error): Protocol.Runtime.evaluateReturnValue {
|
function rewriteError(error: Error): Protocol.Runtime.EvaluateResponse {
|
||||||
if (error.message.includes('Object reference chain is too long'))
|
if (error.message.includes('Object reference chain is too long'))
|
||||||
return { result: { type: 'undefined' } };
|
return { result: { type: 'undefined' } };
|
||||||
if (error.message.includes("Object couldn't be returned by value"))
|
if (error.message.includes("Object couldn't be returned by value"))
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ElementHandle } from './JSHandle';
|
import { ElementHandle } from './JSHandle';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +45,7 @@ export class FileChooser {
|
|||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
element: ElementHandle,
|
element: ElementHandle,
|
||||||
event: Protocol.Page.fileChooserOpenedPayload
|
event: Protocol.Page.FileChooserOpenedEvent
|
||||||
) {
|
) {
|
||||||
this._element = element;
|
this._element = element;
|
||||||
this._multiple = event.mode !== 'selectSingle';
|
this._multiple = event.mode !== 'selectSingle';
|
||||||
|
@ -27,7 +27,7 @@ import { JSHandle, ElementHandle } from './JSHandle';
|
|||||||
import { MouseButton } from './Input';
|
import { MouseButton } from './Input';
|
||||||
import { Page } from './Page';
|
import { Page } from './Page';
|
||||||
import { HTTPResponse } from './HTTPResponse';
|
import { HTTPResponse } from './HTTPResponse';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import {
|
import {
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
EvaluateHandleFn,
|
EvaluateHandleFn,
|
||||||
@ -108,10 +108,7 @@ export class FrameManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
const result = await Promise.all<
|
const result = await Promise.all<{}, Protocol.Page.GetFrameTreeResponse>([
|
||||||
Protocol.Page.enableReturnValue,
|
|
||||||
Protocol.Page.getFrameTreeReturnValue
|
|
||||||
>([
|
|
||||||
this._client.send('Page.enable'),
|
this._client.send('Page.enable'),
|
||||||
this._client.send('Page.getFrameTree'),
|
this._client.send('Page.getFrameTree'),
|
||||||
]);
|
]);
|
||||||
@ -121,7 +118,7 @@ export class FrameManager extends EventEmitter {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._client.send('Page.setLifecycleEventsEnabled', { enabled: true }),
|
this._client.send('Page.setLifecycleEventsEnabled', { enabled: true }),
|
||||||
this._client
|
this._client
|
||||||
.send('Runtime.enable', {})
|
.send('Runtime.enable')
|
||||||
.then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)),
|
.then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)),
|
||||||
this._networkManager.initialize(),
|
this._networkManager.initialize(),
|
||||||
]);
|
]);
|
||||||
@ -210,7 +207,7 @@ export class FrameManager extends EventEmitter {
|
|||||||
return watcher.navigationResponse();
|
return watcher.navigationResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onLifecycleEvent(event: Protocol.Page.lifecycleEventPayload): void {
|
_onLifecycleEvent(event: Protocol.Page.LifecycleEventEvent): void {
|
||||||
const frame = this._frames.get(event.frameId);
|
const frame = this._frames.get(event.frameId);
|
||||||
if (!frame) return;
|
if (!frame) return;
|
||||||
frame._onLifecycleEvent(event.loaderId, event.name);
|
frame._onLifecycleEvent(event.loaderId, event.name);
|
||||||
|
@ -18,7 +18,7 @@ import { Frame } from './FrameManager';
|
|||||||
import { HTTPResponse } from './HTTPResponse';
|
import { HTTPResponse } from './HTTPResponse';
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { helper, debugError } from './helper';
|
import { helper, debugError } from './helper';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@ -123,7 +123,7 @@ export class HTTPRequest {
|
|||||||
frame: Frame,
|
frame: Frame,
|
||||||
interceptionId: string,
|
interceptionId: string,
|
||||||
allowInterception: boolean,
|
allowInterception: boolean,
|
||||||
event: Protocol.Network.requestWillBeSentPayload,
|
event: Protocol.Network.RequestWillBeSentEvent,
|
||||||
redirectChain: HTTPRequest[]
|
redirectChain: HTTPRequest[]
|
||||||
) {
|
) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
@ -17,7 +17,7 @@ import { CDPSession } from './Connection';
|
|||||||
import { Frame } from './FrameManager';
|
import { Frame } from './FrameManager';
|
||||||
import { HTTPRequest } from './HTTPRequest';
|
import { HTTPRequest } from './HTTPRequest';
|
||||||
import { SecurityDetails } from './SecurityDetails';
|
import { SecurityDetails } from './SecurityDetails';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -22,7 +22,7 @@ import { CDPSession } from './Connection';
|
|||||||
import { KeyInput } from './USKeyboardLayout';
|
import { KeyInput } from './USKeyboardLayout';
|
||||||
import { FrameManager, Frame } from './FrameManager';
|
import { FrameManager, Frame } from './FrameManager';
|
||||||
import { getQueryHandlerAndSelector } from './QueryHandler';
|
import { getQueryHandlerAndSelector } from './QueryHandler';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import {
|
import {
|
||||||
EvaluateFn,
|
EvaluateFn,
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
@ -445,11 +445,12 @@ export class ElementHandle<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getBoxModel(): Promise<void | Protocol.DOM.getBoxModelReturnValue> {
|
private _getBoxModel(): Promise<void | Protocol.DOM.GetBoxModelResponse> {
|
||||||
|
const params: Protocol.DOM.GetBoxModelRequest = {
|
||||||
|
objectId: this._remoteObject.objectId,
|
||||||
|
};
|
||||||
return this._client
|
return this._client
|
||||||
.send('DOM.getBoxModel', {
|
.send('DOM.getBoxModel', params)
|
||||||
objectId: this._remoteObject.objectId,
|
|
||||||
})
|
|
||||||
.catch((error) => debugError(error));
|
.catch((error) => debugError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
import { EventEmitter } from './EventEmitter';
|
import { EventEmitter } from './EventEmitter';
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
import { helper, debugError } from './helper';
|
import { helper, debugError } from './helper';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { FrameManager } from './FrameManager';
|
import { FrameManager } from './FrameManager';
|
||||||
import { HTTPRequest } from './HTTPRequest';
|
import { HTTPRequest } from './HTTPRequest';
|
||||||
@ -53,7 +53,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
_requestIdToRequest = new Map<string, HTTPRequest>();
|
_requestIdToRequest = new Map<string, HTTPRequest>();
|
||||||
_requestIdToRequestWillBeSentEvent = new Map<
|
_requestIdToRequestWillBeSentEvent = new Map<
|
||||||
string,
|
string,
|
||||||
Protocol.Network.requestWillBeSentPayload
|
Protocol.Network.RequestWillBeSentEvent
|
||||||
>();
|
>();
|
||||||
_extraHTTPHeaders: Record<string, string> = {};
|
_extraHTTPHeaders: Record<string, string> = {};
|
||||||
_offline = false;
|
_offline = false;
|
||||||
@ -182,7 +182,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRequestWillBeSent(event: Protocol.Network.requestWillBeSentPayload): void {
|
_onRequestWillBeSent(event: Protocol.Network.RequestWillBeSentEvent): void {
|
||||||
// Request interception doesn't happen for data URLs with Network Service.
|
// Request interception doesn't happen for data URLs with Network Service.
|
||||||
if (
|
if (
|
||||||
this._protocolRequestInterceptionEnabled &&
|
this._protocolRequestInterceptionEnabled &&
|
||||||
@ -201,7 +201,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
this._onRequest(event, null);
|
this._onRequest(event, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAuthRequired(event: Protocol.Fetch.authRequiredPayload): void {
|
_onAuthRequired(event: Protocol.Fetch.AuthRequiredEvent): void {
|
||||||
/* TODO(jacktfranklin): This is defined in protocol.d.ts but not
|
/* TODO(jacktfranklin): This is defined in protocol.d.ts but not
|
||||||
* in an easily referrable way - we should look at exposing it.
|
* in an easily referrable way - we should look at exposing it.
|
||||||
*/
|
*/
|
||||||
@ -225,7 +225,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
.catch(debugError);
|
.catch(debugError);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRequestPaused(event: Protocol.Fetch.requestPausedPayload): void {
|
_onRequestPaused(event: Protocol.Fetch.RequestPausedEvent): void {
|
||||||
if (
|
if (
|
||||||
!this._userRequestInterceptionEnabled &&
|
!this._userRequestInterceptionEnabled &&
|
||||||
this._protocolRequestInterceptionEnabled
|
this._protocolRequestInterceptionEnabled
|
||||||
@ -251,7 +251,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onRequest(
|
_onRequest(
|
||||||
event: Protocol.Network.requestWillBeSentPayload,
|
event: Protocol.Network.RequestWillBeSentEvent,
|
||||||
interceptionId?: string
|
interceptionId?: string
|
||||||
): void {
|
): void {
|
||||||
let redirectChain = [];
|
let redirectChain = [];
|
||||||
@ -280,7 +280,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onRequestServedFromCache(
|
_onRequestServedFromCache(
|
||||||
event: Protocol.Network.requestServedFromCachePayload
|
event: Protocol.Network.RequestServedFromCacheEvent
|
||||||
): void {
|
): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
if (request) request._fromMemoryCache = true;
|
if (request) request._fromMemoryCache = true;
|
||||||
@ -302,7 +302,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onResponseReceived(event: Protocol.Network.responseReceivedPayload): void {
|
_onResponseReceived(event: Protocol.Network.ResponseReceivedEvent): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// FileUpload sends a response without a matching request.
|
// FileUpload sends a response without a matching request.
|
||||||
if (!request) return;
|
if (!request) return;
|
||||||
@ -311,7 +311,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
this.emit(NetworkManagerEmittedEvents.Response, response);
|
this.emit(NetworkManagerEmittedEvents.Response, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onLoadingFinished(event: Protocol.Network.loadingFinishedPayload): void {
|
_onLoadingFinished(event: Protocol.Network.LoadingFinishedEvent): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// For certain requestIds we never receive requestWillBeSent event.
|
// For certain requestIds we never receive requestWillBeSent event.
|
||||||
// @see https://crbug.com/750469
|
// @see https://crbug.com/750469
|
||||||
@ -325,7 +325,7 @@ export class NetworkManager extends EventEmitter {
|
|||||||
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
this.emit(NetworkManagerEmittedEvents.RequestFinished, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onLoadingFailed(event: Protocol.Network.loadingFailedPayload): void {
|
_onLoadingFailed(event: Protocol.Network.LoadingFailedEvent): void {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
// For certain requestIds we never receive requestWillBeSent event.
|
// For certain requestIds we never receive requestWillBeSent event.
|
||||||
// @see https://crbug.com/750469
|
// @see https://crbug.com/750469
|
||||||
|
@ -40,7 +40,7 @@ import { TimeoutSettings } from './TimeoutSettings';
|
|||||||
import { FileChooser } from './FileChooser';
|
import { FileChooser } from './FileChooser';
|
||||||
import { ConsoleMessage, ConsoleMessageType } from './ConsoleMessage';
|
import { ConsoleMessage, ConsoleMessageType } from './ConsoleMessage';
|
||||||
import { PuppeteerLifeCycleEvent } from './LifecycleWatcher';
|
import { PuppeteerLifeCycleEvent } from './LifecycleWatcher';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import {
|
import {
|
||||||
SerializableOrJSHandle,
|
SerializableOrJSHandle,
|
||||||
EvaluateHandleFn,
|
EvaluateHandleFn,
|
||||||
@ -527,13 +527,13 @@ export class Page extends EventEmitter {
|
|||||||
waitForDebuggerOnStart: false,
|
waitForDebuggerOnStart: false,
|
||||||
flatten: true,
|
flatten: true,
|
||||||
}),
|
}),
|
||||||
this._client.send('Performance.enable', {}),
|
this._client.send('Performance.enable'),
|
||||||
this._client.send('Log.enable', {}),
|
this._client.send('Log.enable'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _onFileChooser(
|
private async _onFileChooser(
|
||||||
event: Protocol.Page.fileChooserOpenedPayload
|
event: Protocol.Page.FileChooserOpenedEvent
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!this._fileChooserInterceptors.size) return;
|
if (!this._fileChooserInterceptors.size) return;
|
||||||
const frame = this._frameManager.frame(event.frameId);
|
const frame = this._frameManager.frame(event.frameId);
|
||||||
@ -638,7 +638,7 @@ export class Page extends EventEmitter {
|
|||||||
this.emit('error', new Error('Page crashed!'));
|
this.emit('error', new Error('Page crashed!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onLogEntryAdded(event: Protocol.Log.entryAddedPayload): void {
|
private _onLogEntryAdded(event: Protocol.Log.EntryAddedEvent): void {
|
||||||
const { level, text, args, source, url, lineNumber } = event.entry;
|
const { level, text, args, source, url, lineNumber } = event.entry;
|
||||||
if (args) args.map((arg) => helper.releaseObject(this._client, arg));
|
if (args) args.map((arg) => helper.releaseObject(this._client, arg));
|
||||||
if (source !== 'worker')
|
if (source !== 'worker')
|
||||||
@ -1012,7 +1012,7 @@ export class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async deleteCookie(
|
async deleteCookie(
|
||||||
...cookies: Protocol.Network.deleteCookiesParameters[]
|
...cookies: Protocol.Network.DeleteCookiesRequest[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const pageURL = this.url();
|
const pageURL = this.url();
|
||||||
for (const cookie of cookies) {
|
for (const cookie of cookies) {
|
||||||
@ -1121,7 +1121,7 @@ export class Page extends EventEmitter {
|
|||||||
return this._buildMetricsObject(response.metrics);
|
return this._buildMetricsObject(response.metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _emitMetrics(event: Protocol.Performance.metricsPayload): void {
|
private _emitMetrics(event: Protocol.Performance.MetricsEvent): void {
|
||||||
this.emit(PageEmittedEvents.Metrics, {
|
this.emit(PageEmittedEvents.Metrics, {
|
||||||
title: event.title,
|
title: event.title,
|
||||||
metrics: this._buildMetricsObject(event.metrics),
|
metrics: this._buildMetricsObject(event.metrics),
|
||||||
@ -1148,7 +1148,7 @@ export class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _onConsoleAPI(
|
private async _onConsoleAPI(
|
||||||
event: Protocol.Runtime.consoleAPICalledPayload
|
event: Protocol.Runtime.ConsoleAPICalledEvent
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (event.executionContextId === 0) {
|
if (event.executionContextId === 0) {
|
||||||
// DevTools protocol stores the last 1000 console messages. These
|
// DevTools protocol stores the last 1000 console messages. These
|
||||||
@ -1174,7 +1174,7 @@ export class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _onBindingCalled(
|
private async _onBindingCalled(
|
||||||
event: Protocol.Runtime.bindingCalledPayload
|
event: Protocol.Runtime.BindingCalledEvent
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { name, seq, args } = JSON.parse(event.payload);
|
const { name, seq, args } = JSON.parse(event.payload);
|
||||||
let expression = null;
|
let expression = null;
|
||||||
@ -1264,7 +1264,7 @@ export class Page extends EventEmitter {
|
|||||||
this.emit(PageEmittedEvents.Console, message);
|
this.emit(PageEmittedEvents.Console, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onDialog(event: Protocol.Page.javascriptDialogOpeningPayload): void {
|
private _onDialog(event: Protocol.Page.JavascriptDialogOpeningEvent): void {
|
||||||
let dialogType = null;
|
let dialogType = null;
|
||||||
const validDialogTypes = new Set<Protocol.Page.DialogType>([
|
const validDialogTypes = new Set<Protocol.Page.DialogType>([
|
||||||
'alert',
|
'alert',
|
||||||
@ -1307,10 +1307,10 @@ export class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reload(options?: WaitForOptions): Promise<HTTPResponse | null> {
|
async reload(options?: WaitForOptions): Promise<HTTPResponse | null> {
|
||||||
const result = await Promise.all<
|
const result = await Promise.all<HTTPResponse, void>([
|
||||||
HTTPResponse,
|
this.waitForNavigation(options),
|
||||||
Protocol.Page.reloadReturnValue
|
this._client.send('Page.reload'),
|
||||||
>([this.waitForNavigation(options), this._client.send('Page.reload')]);
|
]);
|
||||||
|
|
||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
@ -1386,10 +1386,7 @@ export class Page extends EventEmitter {
|
|||||||
const history = await this._client.send('Page.getNavigationHistory');
|
const history = await this._client.send('Page.getNavigationHistory');
|
||||||
const entry = history.entries[history.currentIndex + delta];
|
const entry = history.entries[history.currentIndex + delta];
|
||||||
if (!entry) return null;
|
if (!entry) return null;
|
||||||
const result = await Promise.all<
|
const result = await Promise.all([
|
||||||
HTTPResponse,
|
|
||||||
Protocol.Page.navigateToHistoryEntryReturnValue
|
|
||||||
>([
|
|
||||||
this.waitForNavigation(options),
|
this.waitForNavigation(options),
|
||||||
this._client.send('Page.navigateToHistoryEntry', { entryId: entry.id }),
|
this._client.send('Page.navigateToHistoryEntry', { entryId: entry.id }),
|
||||||
]);
|
]);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SecurityDetails class represents the security details of a
|
* The SecurityDetails class represents the security details of a
|
||||||
|
@ -19,7 +19,7 @@ import { WebWorker } from './WebWorker';
|
|||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { Browser, BrowserContext } from './Browser';
|
import { Browser, BrowserContext } from './Browser';
|
||||||
import { Viewport } from './PuppeteerViewport';
|
import { Viewport } from './PuppeteerViewport';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -18,7 +18,7 @@ import { debugError } from './helper';
|
|||||||
import { ExecutionContext } from './ExecutionContext';
|
import { ExecutionContext } from './ExecutionContext';
|
||||||
import { JSHandle } from './JSHandle';
|
import { JSHandle } from './JSHandle';
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
import { EvaluateHandleFn, SerializableOrJSHandle } from './EvalTypes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +96,7 @@ export class WebWorker extends EventEmitter {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// This might fail if the target is closed before we recieve all execution contexts.
|
// This might fail if the target is closed before we recieve all execution contexts.
|
||||||
this._client.send('Runtime.enable', {}).catch(debugError);
|
this._client.send('Runtime.enable').catch(debugError);
|
||||||
this._client.on('Runtime.consoleAPICalled', (event) =>
|
this._client.on('Runtime.consoleAPICalled', (event) =>
|
||||||
consoleAPICalled(
|
consoleAPICalled(
|
||||||
event.type,
|
event.type,
|
||||||
|
@ -18,7 +18,7 @@ import { debug } from './Debug';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { CDPSession } from './Connection';
|
import { CDPSession } from './Connection';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import Protocol from '../protocol';
|
import { Protocol } from 'devtools-protocol';
|
||||||
import { CommonEventEmitter } from './EventEmitter';
|
import { CommonEventEmitter } from './EventEmitter';
|
||||||
import { assert } from './assert';
|
import { assert } from './assert';
|
||||||
|
|
||||||
|
15503
src/protocol.d.ts
vendored
15503
src/protocol.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -26,3 +26,7 @@ fs.writeFileSync(
|
|||||||
path.join(__dirname, '..', 'package.json'),
|
path.join(__dirname, '..', 'package.json'),
|
||||||
JSON.stringify(package, undefined, 2) + '\n'
|
JSON.stringify(package, undefined, 2) + '\n'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
'IMPORTANT: you should update the pinned version of devtools-protocol to match the new revsion.'
|
||||||
|
);
|
||||||
|
@ -128,9 +128,19 @@ function checkSources(sources) {
|
|||||||
);
|
);
|
||||||
const name = symbol.getName();
|
const name = symbol.getName();
|
||||||
if (symbol.valueDeclaration && symbol.valueDeclaration.dotDotDotToken) {
|
if (symbol.valueDeclaration && symbol.valueDeclaration.dotDotDotToken) {
|
||||||
const innerType = serializeType(type.typeArguments[0], circular);
|
try {
|
||||||
innerType.name = '...' + innerType.name;
|
const innerType = serializeType(type.typeArguments[0], circular);
|
||||||
return Documentation.Member.createProperty('...' + name, innerType);
|
innerType.name = '...' + innerType.name;
|
||||||
|
return Documentation.Member.createProperty('...' + name, innerType);
|
||||||
|
} catch (error) {
|
||||||
|
/**
|
||||||
|
* DocLint struggles with the paramArgs type on CDPSession.send because
|
||||||
|
* it uses a complex type from the devtools-protocol method. Doclint
|
||||||
|
* isn't going to be here for much longer so we'll just silence this
|
||||||
|
* warning than try to add support which would warrant a huge rewrite.
|
||||||
|
*/
|
||||||
|
if (name !== 'paramArgs') throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Documentation.Member.createProperty(
|
return Documentation.Member.createProperty(
|
||||||
name,
|
name,
|
||||||
|
@ -251,15 +251,23 @@ function compareDocumentations(actual, expected) {
|
|||||||
const actualArgs = Array.from(actualMethod.args.keys());
|
const actualArgs = Array.from(actualMethod.args.keys());
|
||||||
const expectedArgs = Array.from(expectedMethod.args.keys());
|
const expectedArgs = Array.from(expectedMethod.args.keys());
|
||||||
const argsDiff = diff(actualArgs, expectedArgs);
|
const argsDiff = diff(actualArgs, expectedArgs);
|
||||||
|
|
||||||
if (argsDiff.extra.length || argsDiff.missing.length) {
|
if (argsDiff.extra.length || argsDiff.missing.length) {
|
||||||
const text = [
|
/* Doclint cannot handle the parameter type of the CDPSession send method.
|
||||||
`Method ${className}.${methodName}() fails to describe its parameters:`,
|
* so we just ignore it.
|
||||||
];
|
*/
|
||||||
for (const arg of argsDiff.missing)
|
const isCdpSessionSend =
|
||||||
text.push(`- Argument not found: ${arg}`);
|
className === 'CDPSession' && methodName === 'send';
|
||||||
for (const arg of argsDiff.extra)
|
if (!isCdpSessionSend) {
|
||||||
text.push(`- Non-existing argument found: ${arg}`);
|
const text = [
|
||||||
errors.push(text.join('\n'));
|
`Method ${className}.${methodName}() fails to describe its parameters:`,
|
||||||
|
];
|
||||||
|
for (const arg of argsDiff.missing)
|
||||||
|
text.push(`- Argument not found: ${arg}`);
|
||||||
|
for (const arg of argsDiff.extra)
|
||||||
|
text.push(`- Non-existing argument found: ${arg}`);
|
||||||
|
errors.push(text.join('\n'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const arg of argsDiff.equal)
|
for (const arg of argsDiff.equal)
|
||||||
@ -788,6 +796,13 @@ function compareDocumentations(actual, expected) {
|
|||||||
expectedName: 'FrameWaitForFunctionOptions',
|
expectedName: 'FrameWaitForFunctionOptions',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'Method BrowserContext.overridePermissions() permissions',
|
||||||
|
{
|
||||||
|
actualName: 'Array<string>',
|
||||||
|
expectedName: 'Array<Object>',
|
||||||
|
},
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const expectedForSource = expectedNamingMismatches.get(source);
|
const expectedForSource = expectedNamingMismatches.get(source);
|
||||||
@ -825,6 +840,16 @@ function compareDocumentations(actual, expected) {
|
|||||||
* as they will likely be considered "wrong" by DocLint too.
|
* as they will likely be considered "wrong" by DocLint too.
|
||||||
*/
|
*/
|
||||||
if (namingMismatchIsExpected) return;
|
if (namingMismatchIsExpected) return;
|
||||||
|
|
||||||
|
/* Some methods cause errors in the property checks for an unknown reason
|
||||||
|
* so we support a list of methods whose parameters are not checked.
|
||||||
|
*/
|
||||||
|
const skipPropertyChecksOnMethods = new Set([
|
||||||
|
'Method Page.deleteCookie() ...cookies',
|
||||||
|
'Method Page.setCookie() ...cookies',
|
||||||
|
]);
|
||||||
|
if (skipPropertyChecksOnMethods.has(source)) return;
|
||||||
|
|
||||||
const actualPropertiesMap = new Map(
|
const actualPropertiesMap = new Map(
|
||||||
actual.properties.map((property) => [property.name, property.type])
|
actual.properties.map((property) => [property.name, property.type])
|
||||||
);
|
);
|
||||||
|
@ -1,276 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
const path = require('path');
|
|
||||||
const puppeteer = require('../..');
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
|
|
||||||
const fetchAndGenerateProtocolDefinitions = () =>
|
|
||||||
puppeteer
|
|
||||||
.launch({
|
|
||||||
pipe: false,
|
|
||||||
executablePath: process.env.BINARY,
|
|
||||||
})
|
|
||||||
.then(async (browser) => {
|
|
||||||
const origin = browser
|
|
||||||
.wsEndpoint()
|
|
||||||
.match(/ws:\/\/([0-9A-Za-z:\.]*)\//)[1];
|
|
||||||
const page = await browser.newPage();
|
|
||||||
await page.goto(`http://${origin}/json/protocol`);
|
|
||||||
const json = JSON.parse(
|
|
||||||
await page.evaluate(() => document.documentElement.innerText)
|
|
||||||
);
|
|
||||||
const version = await browser.version();
|
|
||||||
await browser.close();
|
|
||||||
const output = `// This is generated from /utils/protocol-types-generator/index.js
|
|
||||||
type binary = string;
|
|
||||||
|
|
||||||
declare module Protocol {${json.domains
|
|
||||||
.map(
|
|
||||||
(domain) => `${
|
|
||||||
domain.description
|
|
||||||
? `
|
|
||||||
/**
|
|
||||||
* ${domain.description}
|
|
||||||
*/`
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
export module ${domain.domain} {${(domain.types || [])
|
|
||||||
.map(
|
|
||||||
(type) =>
|
|
||||||
`${
|
|
||||||
type.description
|
|
||||||
? `
|
|
||||||
/**
|
|
||||||
* ${type.description}
|
|
||||||
*/`
|
|
||||||
: ''
|
|
||||||
}${
|
|
||||||
type.properties
|
|
||||||
? `
|
|
||||||
export interface ${type.id} {${(type.properties || [])
|
|
||||||
.map(
|
|
||||||
(property) => `${
|
|
||||||
property.description
|
|
||||||
? `
|
|
||||||
/**
|
|
||||||
* ${property.description}
|
|
||||||
*/`
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
${property.name}${property.optional ? '?' : ''}: ${typeOfProperty(
|
|
||||||
property
|
|
||||||
)};`
|
|
||||||
)
|
|
||||||
.join(``)}
|
|
||||||
}`
|
|
||||||
: `
|
|
||||||
export type ${type.id} = ${typeOfProperty(type)};`
|
|
||||||
}`
|
|
||||||
)
|
|
||||||
.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('')}
|
|
||||||
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('')}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Protocol;
|
|
||||||
`;
|
|
||||||
|
|
||||||
return { output, version };
|
|
||||||
});
|
|
||||||
|
|
||||||
const protocolOutputPath = path.join(__dirname, '../../src/protocol.d.ts');
|
|
||||||
const relativeProtocolOutputPath = path.relative(
|
|
||||||
process.cwd(),
|
|
||||||
protocolOutputPath
|
|
||||||
);
|
|
||||||
|
|
||||||
const writeOutputToDisk = ({ output, version }) => {
|
|
||||||
require('fs').writeFileSync(protocolOutputPath, output);
|
|
||||||
console.log(
|
|
||||||
`Wrote protocol.d.ts for ${version} to ${relativeProtocolOutputPath}`
|
|
||||||
);
|
|
||||||
console.log(`You should commit the changes.`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const lastCommitMessage = () => {
|
|
||||||
return execSync('git log --no-merges -n 1', { encoding: 'utf8' });
|
|
||||||
};
|
|
||||||
|
|
||||||
const cli = async () => {
|
|
||||||
const scriptToRun = process.argv[2];
|
|
||||||
const changeExpected = lastCommitMessage().includes('EXPECTED_PROTOCOL_DIFF');
|
|
||||||
|
|
||||||
if (scriptToRun === 'update') {
|
|
||||||
writeOutputToDisk(await fetchAndGenerateProtocolDefinitions());
|
|
||||||
} else if (scriptToRun === 'compare') {
|
|
||||||
const { output } = await fetchAndGenerateProtocolDefinitions();
|
|
||||||
const outputOnDisk = require('fs').readFileSync(protocolOutputPath, {
|
|
||||||
encoding: 'utf8',
|
|
||||||
});
|
|
||||||
if (output === outputOnDisk) {
|
|
||||||
console.log(`Success: ${relativeProtocolOutputPath} is up to date.`);
|
|
||||||
} else if (changeExpected) {
|
|
||||||
console.log(`Warning: ${relativeProtocolOutputPath} is out of date`);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
' continuing because EXPECTED_PROTOCOL_DIFF was found in the last commit message.'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log(`Error: ${relativeProtocolOutputPath} is out of date.`);
|
|
||||||
console.log(
|
|
||||||
'You should run `npm run update-protocol-d-ts` and commit the changes.'
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(`Unknown protocol script ${scriptToRun}.`);
|
|
||||||
console.log(`Valid scripts are:
|
|
||||||
- update: fetch and update ${relativeProtocolOutputPath}
|
|
||||||
- compare: check ${relativeProtocolOutputPath} is up to date with the latest CDP.
|
|
||||||
`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
cli();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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('|');
|
|
||||||
switch (property.type) {
|
|
||||||
case 'array':
|
|
||||||
return typeOfProperty(property.items, domain) + '[]';
|
|
||||||
case 'integer':
|
|
||||||
return 'number';
|
|
||||||
}
|
|
||||||
return property.type;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user