aboutsummaryrefslogtreecommitdiff
path: root/src/domains/forms.ts
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmail.com>2026-07-27 23:26:50 +0530
committerAman Kumar <145339995+amankumarsingh77@users.noreply.github.com>2026-08-02 19:12:46 +0530
commit9f2f75dd9281153888776e5d39d4926655c15f2a (patch)
tree89c23c8ad333b5096d39b661b142eaad544cf004 /src/domains/forms.ts
parent931576443dcb990761cb7e68e354465145f9292d (diff)
refactor(domains): drop CDP casts, share the box-model unwrap
ref-resolve.ts and snapshot.ts had the same box-model unwrap, both using data.model! to work around an untyped response. Extracted to domains/box.ts; the typed schema makes the assertions unnecessary. Both derived the centre identically (quad corner + half the model width/height), so centreOf keeps that derivation; the shared zero-size rejection moved into boxOf, and snapshot keeps its own off-viewport (x/y < 0) filter. evalInIsolatedTab now goes through evaluateJson with the tab's own sessionId and a caller-supplied guard; both callers evaluate expressions ending in JSON.stringify, so they pass isJsonText rather than a check that checks nothing. Runtime.evaluate/callFunctionOn result casts in form.ts, forms.ts and keyboard.ts are replaced by named guards over the in-page result shapes. Runtime.callFunctionOn's params schema gained arguments/returnByValue/ awaitPromise/userGesture: four domain call sites legitimately pass them and typebox's additionalProperties:true does not widen the static type, so the params type was rejecting valid CDP fields. Params schemas are type-only (only results are compiled), so this is a compile-time widening with no runtime effect. tsc is green again for both tsconfigs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'src/domains/forms.ts')
-rw-r--r--src/domains/forms.ts30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/domains/forms.ts b/src/domains/forms.ts
index 1d83ba6..e38af9a 100644
--- a/src/domains/forms.ts
+++ b/src/domains/forms.ts
@@ -128,6 +128,23 @@ type PageResult = {
readonly options?: ReadonlyArray<{ value: string; text: string }>;
};
+const isOption = (v: unknown): v is { readonly value: string; readonly text: string } =>
+ typeof v === "object" && v !== null
+ && "value" in v && typeof v.value === "string"
+ && "text" in v && typeof v.text === "string";
+
+const isPageResult = (v: unknown): v is PageResult => {
+ if (typeof v !== "object" || v === null) return false;
+ if (!("ok" in v) || typeof v.ok !== "boolean") return false;
+ if ("reason" in v && typeof v.reason !== "string") return false;
+ if ("kind" in v && typeof v.kind !== "string") return false;
+ if ("text" in v && typeof v.text !== "string") return false;
+ if ("checked" in v && typeof v.checked !== "boolean") return false;
+ if ("changed" in v && typeof v.changed !== "boolean") return false;
+ if ("options" in v && !(Array.isArray(v.options) && v.options.every(isOption))) return false;
+ return true;
+};
+
/**
* Resolve a ref (CDP backendDOMNodeId) to a live JS handle and invoke a
* page-side function on it. DOM + Runtime are enabled on every session
@@ -149,7 +166,7 @@ const resolveAndCall = async (
details: { ref },
});
}
- const objectId = (resolved.data as { object?: { objectId?: string } }).object?.objectId;
+ const objectId = resolved.data.object.objectId;
if (objectId === undefined) {
return err({
kind: "invalid_state",
@@ -167,15 +184,14 @@ const resolveAndCall = async (
awaitPromise: true,
});
if (!called.success) return err({ kind: "cdp_error", message: called.error.message, details: { ref } });
- const data = called.data as { result?: { value?: unknown }; exceptionDetails?: unknown };
- if (data.exceptionDetails !== undefined) {
- return err({ kind: "cdp_error", message: `page function threw: ${JSON.stringify(data.exceptionDetails)}`, details: { ref } });
+ if (called.data.exceptionDetails !== undefined) {
+ return err({ kind: "cdp_error", message: `page function threw: ${JSON.stringify(called.data.exceptionDetails)}`, details: { ref } });
}
- const value = data.result?.value;
- if (typeof value !== "object" || value === null) {
+ const value = called.data.result.value;
+ if (!isPageResult(value)) {
return err({ kind: "internal", message: "page function returned no result object", details: { ref } });
}
- return ok(value as PageResult);
+ return ok(value);
} finally {
// Best-effort: release the remote handle so it can be GC'd. Failure is
// harmless (the page may have navigated), so we ignore the result.