Introduce `Page.onResponse`

ZI
17h ago
+199-25

Add dedicated Page.onResponse() event listener, matching Playwright's Page.on("response") (docs).

PR Stack

  1. This PR
  2. #3385
  3. #3386

Architecture

There are two broad stroke changes:

  1. Drilling a "response subscription" all the way from the SDK client Page through -> RPC -> StagehandRuntime -> Understudy Page -> NetworkManager -> CDP.
  2. Using the existing class Response as the callback return type! We hold references to these objects in a new ResponseHandlerTable that gets looked up whenever the SDK client asks for it.
flowchart TB
    subgraph CLIENT["SDK client"]
        PAGE["Page<br/>+onResponse()<br/>+on_response()"]
        SDKRESP["Response<br/>body() · text() · json()"]
        RPC["RPCClient"]

        RPC -.->|"page.event"| PAGE
        PAGE -->|"listener(response)"| SDKRESP
        SDKRESP -->|"response.body(responseId)"| RPC
    end

    subgraph SW["Extension worker"]
        RUNTIME["StagehandRuntime<br/>±pageOn()"]
        HANDLES["+ResponseHandleTable"]

        RUNTIME -->|"register(response)"| HANDLES
        HANDLES -.->|"responseId"| RUNTIME
        RUNTIME -->|"resolve(responseId)"| HANDLES
        HANDLES -->|"stored Response → body()"| LIVE

        subgraph UNDERSTUDY["Understudy"]
            UPAGE["Page<br/>+subscribeResponse()"]
            NETWORK["NetworkManager<br/>+subscribeResponse()"]
            LIVE["Response<br/>body() · finished() · loadBody()"]
            CDP["CdpConnection / CDPSession"]

            UPAGE -->|"subscribeResponse(listener)"| NETWORK
            NETWORK -->|"new Response()"| LIVE
            CDP -->|"Network.responseReceived"| NETWORK
            LIVE -->|"Network.getResponseBody"| CDP
        end

        RUNTIME -->|"subscribeResponse(listener)"| UPAGE
    end

    subgraph BROWSER["Chrome browser targets"]
        TARGETS["Page / child frames"]
    end

    RPC -->|"JSON-RPC over CDP"| SW
    CDP <-->|"CDP"| TARGETS

    classDef edited fill:#dcfce7,stroke:#16a34a,color:#14532d,stroke-width:2px;
    classDef existing fill:#f4f4f5,stroke:#a1a1aa,color:#27272a;

    class PAGE,RUNTIME,HANDLES,UPAGE,NETWORK edited;
    class SDKRESP,RPC,LIVE,CDP,TARGETS existing;