feat: add browser-side function waits to the extension

Merged
SU
8d ago
+753-65

why

Add browser-side function waiting without repeatedly evaluating over the SDK transport.

This is PR1 of the waitForFunction() stack. Follow-up #3183 targets this branch to register the RPC and expose it in TypeScript, Python, and Go.

what changed

  • Poll an expression in the main world immediately, then on animation frames or a positive interval; await asynchronous predicates without overlapping calls.
  • Return a detached JSON value and surface predicate/serialization errors directly.
  • Reuse the selector-wait handle lifecycle through one shared browser-wait helper, including disposal and late-result cleanup.
  • Keep one Progress deadline across navigation retries. Timeout zero remains unlimited, but closed pages/transports stop retries.
  • Distinguish browser predicate exceptions from transient CDP errors so a matching error message never triggers accidental retries.
  • Refresh the required embedded extension ZIP. No protocol/RPC or public SDK API changes.

Reviewed with the requested Thermo-Nuclear Code Quality Review skill: shared resource ownership replaces duplicated cleanup, and browser-side polling stays out of the transport and SDK layers.

test plan

  • 79 focused extension tests passed, including the existing selector-wait regressions.
  • Covers async predicates, errors, invalid polling, timeout/late cleanup, context/root-frame replacement, and closure during readiness/retry with timeout zero.
  • Extension build/typecheck, embedded ZIP regeneration, formatting, and git diff --check passed.
  • Public real-Chrome integration coverage is in the SDK follow-up.