MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / CdpPage

Class CdpPage

e2e/src/vm/desktop.ts:246–310  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

244}
245
246export class CdpPage {
247 private nextId = 1;
248 private readonly pending = new Map<number, (value: unknown) => void>();
249
250 private constructor(private readonly socket: WebSocket) {
251 socket.addEventListener("message", (event) => {
252 if (typeof event.data !== "string") return;
253 const message = JSON.parse(event.data) as { id?: number; result?: unknown };
254 if (message.id && this.pending.has(message.id)) {
255 this.pending.get(message.id)!(message.result);
256 this.pending.delete(message.id);
257 }
258 });
259 }
260
261 static connect = (url: string): Promise<CdpPage> =>
262 new Promise((resolve, reject) => {
263 const socket = new WebSocket(url);
264 const timer = setTimeout(
265 // oxlint-disable-next-line executor/no-promise-reject, executor/no-error-constructor -- boundary: WebSocket connection promise adapter
266 () => reject(new Error(`CDP connect timeout: ${url}`)),
267 30_000,
268 );
269 socket.addEventListener("open", () => {
270 clearTimeout(timer);
271 resolve(new CdpPage(socket));
272 });
273 socket.addEventListener("error", () => {
274 clearTimeout(timer);
275 // oxlint-disable-next-line executor/no-promise-reject, executor/no-error-constructor -- boundary: WebSocket connection promise adapter
276 reject(new Error(`CDP connect failed: ${url}`));
277 });
278 });
279
280 command = <T>(method: string, params: Record<string, unknown> = {}): Promise<T> => {
281 const id = this.nextId++;
282 const result = new Promise<T>((resolve) =>
283 this.pending.set(id, (value) => resolve(value as T)),
284 );
285 this.socket.send(JSON.stringify({ id, method, params }));
286 return result;
287 };
288
289 waitForText = async (text: string, timeoutMs: number): Promise<void> => {
290 const deadline = Date.now() + timeoutMs;
291 const expression = `document.body?.innerText.includes(${JSON.stringify(text)}) ?? false`;
292 for (;;) {
293 const r = await this.command<{ result?: { value?: boolean } }>("Runtime.evaluate", {
294 expression,
295 returnByValue: true,
296 });
297 if (r.result?.value) return;
298 // oxlint-disable-next-line executor/no-error-constructor -- boundary: a wait timeout is a plain failure here
299 if (Date.now() >= deadline) throw new Error(`timed out waiting for text: ${text}`);
300 await sleep(250);
301 }
302 };
303

Callers

nothing calls this directly

Calls 6

rejectFunction · 0.85
setMethod · 0.80
sleepFunction · 0.70
sendMethod · 0.65
closeMethod · 0.65
resolveFunction · 0.50

Tested by

no test coverage detected