Files
fn_registry/functions/browser/cdp_handle_dialog.md
T
egutierrez 8742cb25be feat(browser): auto-commit con 60 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-07 11:42:31 +02:00

4.4 KiB

id, name, kind, lang, domain, purity, version, tested, tests, test_file_path, description, tags, signature, uses_functions, uses_types, returns, returns_optional, error_type, imports, file_path, example, params, output
id name kind lang domain purity version tested tests test_file_path description tags signature uses_functions uses_types returns returns_optional error_type imports file_path example params output
cdp_handle_dialog_go_browser cdp_handle_dialog function go browser impure 1.1.0 true
TestCdpHandleDialog_nilConn
TestDialogLog
functions/browser/cdp_handle_dialog_test.go Instala un auto-handler que responde automaticamente a dialogos JS (alert/confirm/prompt/beforeunload) via Page.javascriptDialogOpening CDP hasta que se llame el cancel devuelto. Devuelve un *DialogLog con Count/LastType/LastMessage de lo auto-respondido. Un unico worker serializa las respuestas (no spawnea una goroutine por dialogo).
cdp
browser
dialog
input
navegator
func CdpHandleDialog(c *CDPConn, accept bool, promptText string) (func(), *DialogLog, error)
false error_go_core
functions/browser/cdp_handle_dialog.go // Aceptar automaticamente confirm() antes de navegar cancel, _ := CdpHandleDialog(c, true, "") defer cancel() _ = CdpClick(c, "#delete-account-btn") _ = CdpWaitIdle(c, 2000)
name desc
c Conexion CDP activa obtenida con CdpConnect.
name desc
accept true para aceptar/OK el dialogo; false para rechazar/Cancel. Para alert() el valor no importa (siempre se cierra), para confirm() determina el valor de retorno, para prompt() determina si se devuelve el texto o null.
name desc
promptText Texto a inyectar en dialogos prompt(). Vacio string para no inyectar texto. Ignorado en alert() y confirm().
(cancel func(), *DialogLog, error): cancel des-registra el handler y detiene el worker (idempotente, seguro llamarlo varias veces); DialogLog acumula Count/LastType/LastMessage de lo auto-respondido (leer con Snapshot()); error si la conexion es nula o Page.enable falla.

Ejemplo

conn, _ := CdpConnect(9222)
_ = CdpNavigate(conn, "https://example.com/admin")
_ = CdpWaitLoad(conn, 3*time.Second)

// Instalar handler antes de la accion que dispara el dialogo
cancel, dlog, err := CdpHandleDialog(conn, true, "")
if err != nil {
    log.Fatal(err)
}
defer cancel()

// Este boton dispara confirm("¿Seguro que quieres borrar?")
// El handler lo acepta automaticamente sin bloquear
_ = CdpClick(conn, "#btn-delete-all")
_ = CdpWaitIdle(conn, CdpWaitIdleOpts{})

// Saber qué se auto-respondió
count, lastType, lastMsg := dlog.Snapshot()
fmt.Printf("auto-respondidos: %d (último %s: %q)\n", count, lastType, lastMsg)

Cuando usarla

Instalar antes de cualquier accion que pueda disparar alert(), confirm(), prompt() o beforeunload en la pagina. Sin este handler, el dialogo bloquea el tab del navegador indefinidamente y todas las llamadas CDP siguientes se quedan colgadas esperando. Imprescindible en scraping de paneles de administracion, flujos de borrado con confirmacion, y paginas con beforeunload que pregunta si quieres salir.

Gotchas

  • DEADLOCK GARANTIZADO si se llama sendCDP de forma sincrona dentro del handler de evento. El handler corre en la goroutine de lectura del WebSocket; sendCDP espera una respuesta que esa misma goroutine deberia leer. La implementacion encola el evento en un canal y lo responde desde UN worker aparte — no modificar este patron.
  • Un único worker, no goroutine por diálogo: el handler antiguo hacía go c.sendCDP(...) por cada diálogo (spawn ilimitado). Ahora encola en un canal con buffer (64) que consume un worker. Si la página dispara una tormenta de diálogos que llena el buffer, los excedentes se descartan (no se responden) para no colgar la conexión — caso patológico, raro en la práctica.
  • Leer el log con Snapshot(): DialogLog tiene mutex interno. En concurrencia, usa dlog.Snapshot() en vez de leer los campos públicos directamente (evita data race con el worker).
  • El handler responde todos los diálogos con los mismos accept y promptText hasta que se llame cancel().
  • cancel() es idempotente (seguro llamarlo varias veces) y detiene el worker. No cierra diálogos ya abiertos; solo evita responder los futuros.
  • Para beforeunload, accept: true permite la navegacion y accept: false la bloquea.

Capability growth log

  • v1.1.0 (2026-06-06) — devuelve *DialogLog (Count/LastType/LastMessage) para que el caller sepa qué se auto-respondió; reemplaza el spawn de una goroutine por diálogo por un worker único alimentado por canal con buffer; cancel() ahora idempotente vía sync.Once.