mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
* refactor(browser): send only CDP commands with registered result schemas * refactor(browser): open Playwright CDP sessions only through the registered-command owner * fix(browser): keep the restore obligation for an applied override with a malformed reply A schema-rejected success reply means the browser applied the Emulation override, so the attached environment owner records the reset obligation before reporting the protocol error. Only a rejected or unanswered command leaves no obligation. * refactor(browser): open verifier-script CDP sessions through the registered-command owner (#10710) * fix(browser): register the CDP commands JavaScript verifiers send The verifier scripts send Browser.close, Page.createIsolatedWorld, Page.navigate, Page.reload, Target.activateTarget, Target.closeTarget and Target.createTarget through CdpConnection, which now admits every reply through its command's result schema. Register those schemas, refuse an unregistered run-time name as a typed malformed reply instead of a TypeError, and check script send literals against the registry. * fix(browser): keep Target.closeTarget's success member for the verifiers
52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
import { err, ok, type Result } from "../domain/result.js";
|
|
import {
|
|
CdpMalformedReply,
|
|
type CdpCommand,
|
|
type CdpCommandParams,
|
|
type CdpCommandResult,
|
|
} from "./protocol/CdpCommands.js";
|
|
import { CdpCommandRejection } from "./CdpCommandRejection.js";
|
|
import { CdpConnection } from "./CdpConnection.js";
|
|
|
|
/** Why an optional command left its section without a reply. */
|
|
export type CdpOptionalCommandGap =
|
|
| { readonly _tag: "CdpCommandUnavailable" }
|
|
| { readonly _tag: "CdpMalformedReply"; readonly reply: CdpMalformedReply };
|
|
|
|
/**
|
|
* Execute an optional CDP method. "Method not found" and a reply that fails
|
|
* its result schema are returned as gaps for the caller's section to record;
|
|
* transport and cancellation failures still propagate.
|
|
*/
|
|
export const optionalCdpCommand = async <M extends CdpCommand>(
|
|
context: {
|
|
readonly connection: CdpConnection;
|
|
readonly sessionId: string | undefined;
|
|
readonly signal?: AbortSignal;
|
|
},
|
|
method: M,
|
|
parameters: CdpCommandParams<M>,
|
|
limitations: string[],
|
|
): Promise<Result<CdpCommandResult<M>, CdpOptionalCommandGap>> => {
|
|
try {
|
|
return ok(
|
|
await context.connection.send(
|
|
method,
|
|
parameters,
|
|
context.sessionId,
|
|
context.signal,
|
|
),
|
|
);
|
|
} catch (cause: unknown) {
|
|
if (cause instanceof CdpMalformedReply) {
|
|
const limitation = `${method} returned a malformed result; the section that reads it is incomplete.`;
|
|
if (!limitations.includes(limitation)) limitations.push(limitation);
|
|
return err({ _tag: "CdpMalformedReply", reply: cause });
|
|
}
|
|
if (!(cause instanceof CdpCommandRejection) || cause.code !== -32_601)
|
|
throw cause;
|
|
limitations.push(`${method} was unavailable from this browser target.`);
|
|
return err({ _tag: "CdpCommandUnavailable" });
|
|
}
|
|
};
|