Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"sizzle": "2.3.6",
"socket.io": "4.7.5",
"socket.io-client": "4.7.5",
"source-map": "0.7.4",
"source-map": "0.7.6",
"strftime": "0.10.2",
"strip-ansi": "6.0.1",
"temp": "0.8.3",
Expand Down
8 changes: 4 additions & 4 deletions src/browser/cdp/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export class CDPConnection {
this._pingHealthCheckStart();

const onPing = (): void => result.pong();
const _onMessage = (data: RawData): void => this._onMessage(data);
const onMessage = (data: RawData): void => this._onMessage(data);
const onError = (err: Error): void => {
if (result === this._wsConnection) {
this._closeWsConnection(
Expand All @@ -190,11 +190,11 @@ export class CDPConnection {
};

result.on("ping", onPing);
result.on("message", _onMessage);
result.on("message", onMessage);
result.on("error", onError);
result.once("close", () => {
result.off("ping", onPing);
result.off("message", _onMessage);
result.off("message", onMessage);
result.off("error", onError);
if (result === this._wsConnection) {
this._closeWsConnection(
Expand Down Expand Up @@ -388,7 +388,7 @@ export class CDPConnection {
}

/** @description Performs high-level CDP request with retries and timeouts */
async request<T>(
async request<T = void>(
method: CDPRequest["method"],
{ params, sessionId }: Omit<CDPRequest, "id" | "method"> = {},
): Promise<T> {
Expand Down
66 changes: 66 additions & 0 deletions src/browser/cdp/domains/css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { CDPConnection } from "../connection";
import { CDPEventEmitter } from "../emitter";
import type { CDPCSSStyleSheetHeader, CDPSessionId, CDPStyleSheetId } from "../types";

interface StopRuleUsageTrackingResponse {
ruleUsage: Array<{
styleSheetId: CDPStyleSheetId;
startOffset: number;
endOffset: number;
used: boolean;
}>;
}

export interface CssEvents {
fontsUpdated: {
font: Record<string, unknown>;
};
mediaQueryResultChanged: Record<string, never>;
styleSheetAdded: {
header: CDPCSSStyleSheetHeader;
};
styleSheetChanged: {
styleSheetId: CDPStyleSheetId;
};
styleSheetRemoved: {
styleSheetId: CDPStyleSheetId;
};
}

/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/ */
export class CDPCss extends CDPEventEmitter<CssEvents> {
private readonly _connection: CDPConnection;

public constructor(connection: CDPConnection) {
super();

this._connection = connection;
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/#method-enable */
async enable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("CSS.enable", { sessionId });
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/#method-disable */
async disable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("CSS.disable", { sessionId });
}

/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/#method-getStyleSheetText */
async getStyleSheetText(sessionId: CDPSessionId, styleSheetId: CDPStyleSheetId): Promise<{ text: string }> {
return this._connection.request("CSS.getStyleSheetText", { sessionId, params: { styleSheetId } });
}

/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/#method-startRuleUsageTracking */
async startRuleUsageTracking(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("CSS.startRuleUsageTracking", { sessionId });
}

/** @link https://chromedevtools.github.io/devtools-protocol/tot/CSS/#method-stopRuleUsageTracking */
async stopRuleUsageTracking(sessionId: CDPSessionId): Promise<StopRuleUsageTrackingResponse> {
return this._connection.request("CSS.stopRuleUsageTracking", { sessionId });
}
}
92 changes: 92 additions & 0 deletions src/browser/cdp/domains/debugger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { CDPConnection } from "../connection";
import { CDPEventEmitter } from "../emitter";
import type {
CDPDebuggerCallFrame,
CDPDebuggerPausedReason,
CDPExecutionContextId,
CDPRuntimeScriptId,
CDPRuntimeStackTrace,
CDPSessionId,
} from "../types";

interface ScriptData {
scriptId: CDPRuntimeScriptId;
/** URL or name of the script parsed (if any). */
url: string;
/** Line offset of the script within the resource with given URL (for script tags). */
startLine: number;
/** Column offset of the script within the resource with given URL. */
startColumn: number;
/** Last line of the script. */
endLine: number;
/** Length of the last line of the script. */
endColumn: number;
executionContextId: CDPExecutionContextId;
/** Content hash of the script, SHA-256. */
hash: string;
/** For Wasm modules, the content of the build_id custom section. For JavaScript the debugId magic comment. */
buildId: string;
/** Embedder-specific auxiliary data likely matching {isDefault: boolean, type: 'default'|'isolated'|'worker', frameId: string} */
executionContextAuxData?: Record<string, unknown>;
sourceMapURL?: string;
/** True, if this script has sourceURL. */
hasSourceURL?: boolean;
/** True, if this script is ES6 module. */
isModule?: boolean;
/** This script length. */
length?: number;
}

interface GetScriptSourceResponse {
/** Script source (empty in case of Wasm bytecode). */
scriptSource: string;
/** Wasm bytecode. (Encoded as a base64 string when passed over JSON) */
bytecode?: string;
}

export interface DebuggerEvents {
paused: {
callFrames: CDPDebuggerCallFrame;
/** Location of console.profileEnd(). */
reason: CDPDebuggerPausedReason;
/** Object containing break-specific auxiliary properties. */
data?: Record<string, unknown>;
asyncStackTrace?: CDPRuntimeStackTrace;
};
resumed: Record<never, unknown>;
scriptFailedToParse: ScriptData;
scriptParsed: ScriptData;
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Debugger/ */
export class CDPDebugger extends CDPEventEmitter<DebuggerEvents> {
private readonly _connection: CDPConnection;

public constructor(connection: CDPConnection) {
super();

this._connection = connection;
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Debugger/#method-disable */
async disable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("Debugger.disable", { sessionId });
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Debugger/#method-enable */
async enable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("Debugger.enable", { sessionId });
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Debugger/#method-resume */
async resume(sessionId: CDPSessionId, terminateOnResume?: boolean): Promise<void> {
return this._connection.request("Debugger.resume", { sessionId, params: { terminateOnResume } });
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Debugger/#method-getScriptSource */
async getScriptSource(sessionId: CDPSessionId, scriptId: CDPRuntimeScriptId): Promise<GetScriptSourceResponse> {
return this._connection.request("Debugger.getScriptSource", { sessionId, params: { scriptId } });
}
}
37 changes: 37 additions & 0 deletions src/browser/cdp/domains/dom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CDPConnection } from "../connection";
import { CDPEventEmitter } from "../emitter";
import type { CDPSessionId } from "../types";

export interface DomEvents {
attributeModified: Record<string, unknown>;
attributeRemoved: Record<string, unknown>;
characterDataModified: Record<string, unknown>;
childNodeCountUpdated: Record<string, unknown>;
childNodeInserted: Record<string, unknown>;
childNodeRemoved: Record<string, unknown>;
documentUpdated: Record<string, unknown>;
setChildNodes: Record<string, unknown>;
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Dom/ */
export class CDPDom extends CDPEventEmitter<DomEvents> {
private readonly _connection: CDPConnection;

public constructor(connection: CDPConnection) {
super();

this._connection = connection;
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/1-3/DOM/#method-enable */
async enable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("DOM.enable", { sessionId });
}

/** @param sessionId result of "Target.attachToTarget" */
/** @link https://chromedevtools.github.io/devtools-protocol/1-3/DOM/#method-disable */
async disable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("DOM.disable", { sessionId });
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CDPConnection } from "./connection";
import { CDPEventEmitter } from "./emitter";
import type { CDPDebuggerLocation, CDPSessionId, CDPScriptCoverage, CDPProfile } from "./types";
import { CDPConnection } from "../connection";
import { CDPEventEmitter } from "../emitter";
import type { CDPDebuggerLocation, CDPSessionId, CDPScriptCoverage, CDPProfile } from "../types";

interface StartPreciseCoverageRequest {
/** Collect accurate call counts beyond simple 'covered' or 'not covered'. */
Expand Down Expand Up @@ -72,10 +72,7 @@ export class CDPProfiler extends CDPEventEmitter<ProfilerEvents> {
sessionId: CDPSessionId,
params: StartPreciseCoverageRequest,
): Promise<StartPreciseCoverageResponse> {
return this._connection.request<StartPreciseCoverageResponse>("Profiler.startPreciseCoverage", {
sessionId,
params,
});
return this._connection.request("Profiler.startPreciseCoverage", { sessionId, params });
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Profiler/#method-stopPreciseCoverage */
Expand All @@ -85,6 +82,6 @@ export class CDPProfiler extends CDPEventEmitter<ProfilerEvents> {

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Profiler/#method-takePreciseCoverage */
async takePreciseCoverage(sessionId: CDPSessionId): Promise<TakePreciseCoverageResponse> {
return this._connection.request<TakePreciseCoverageResponse>("Profiler.takePreciseCoverage", { sessionId });
return this._connection.request("Profiler.takePreciseCoverage", { sessionId });
}
}
74 changes: 74 additions & 0 deletions src/browser/cdp/domains/runtime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { CDPConnection } from "../connection";
import { CDPEventEmitter } from "../emitter";
import type { CDPExecutionContextId, CDPRuntimeRemoteObject, CDPSessionId } from "../types";

interface EvaluateRequest {
/** Expression to evaluate. */
expression: string;
/** Symbolic group name that can be used to release multiple objects. */
objectGroup?: string;
/** Determines whether Command Line API should be available during the evaluation. */
includeCommandLineAPI?: boolean;
/** In silent mode exceptions thrown during evaluation are not reported and do not pause execution. Overrides setPauseOnException state. */
silent?: boolean;
/** Specifies in which execution context to perform evaluation. If the parameter is omitted the evaluation will be performed in the context of the inspected page. This is mutually exclusive with uniqueContextId, which offers an alternative way to identify the execution context that is more reliable in a multi-process environment. */
contextId?: CDPExecutionContextId;
/** Whether the result is expected to be a JSON object that should be sent by value. */
returnByValue?: boolean;
/** Whether execution should be treated as initiated by user in the UI. */
userGesture?: boolean;
/** Whether execution should await for resulting value and return once awaited promise is resolved. */
awaitPromise?: boolean;
}

interface EvaluateResponse<T> {
/** Evaluation result. */
result: CDPRuntimeRemoteObject<T>;
/** Exception details. */
exceptionDetails?: Record<string, unknown>;
}

export interface RuntimeEvents {
consoleAPICalled: Record<string, unknown>;
exceptionRevoked: Record<string, unknown>;
exceptionThrown: Record<string, unknown>;
executionContextCreated: Record<string, unknown>;
executionContextDestroyed: Record<string, unknown>;
executionContextsCleared: Record<string, unknown>;
inspectRequested: Record<string, unknown>;
}

/** @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/ */
export class CDPRuntime extends CDPEventEmitter<RuntimeEvents> {
private readonly _connection: CDPConnection;

public constructor(connection: CDPConnection) {
super();

this._connection = connection;
}

/**
* @param sessionId result of "Target.attachToTarget"
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#method-evaluate
*/
async evaluate<T>(sessionId: CDPSessionId, params: EvaluateRequest): Promise<EvaluateResponse<T>> {
return this._connection.request("Runtime.evaluate", { sessionId, params });
}

/**
* @param sessionId result of "Target.attachToTarget"
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#method-enable
*/
async enable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("Runtime.enable", { sessionId });
}

/**
* @param sessionId result of "Target.attachToTarget"
* @link https://chromedevtools.github.io/devtools-protocol/1-3/Runtime/#method-disable
*/
async disable(sessionId: CDPSessionId): Promise<void> {
return this._connection.request("Runtime.disable", { sessionId });
}
}
Loading
Loading