chore: auto-commit (97 archivos)
- .claude/CLAUDE.md - .claude/agents/fn-recopilador/SKILL.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - bash/functions/infra/build_cpp_windows.sh - cpp/CMakeLists.txt - cpp/PATTERNS.md - cpp/framework/app_base.cpp - cpp/framework/app_base.h - dev/issues/README.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,18 +16,25 @@ import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// EventHandler es invocado cuando llega un evento CDP del metodo subscrito.
|
||||
// El handler corre en la goroutine del readLoop — debe ser rapido o despachar
|
||||
// a un canal/goroutine propio. params puede ser nil si Chrome no envia.
|
||||
type EventHandler func(method string, params map[string]any)
|
||||
|
||||
// CDPConn es una conexion activa al Chrome DevTools Protocol.
|
||||
// Gestiona el WebSocket raw y el protocolo JSON-RPC de CDP.
|
||||
type CDPConn struct {
|
||||
conn net.Conn
|
||||
reader *bufio.Reader
|
||||
mu sync.Mutex
|
||||
nextID atomic.Int64
|
||||
port int
|
||||
pid int
|
||||
pending map[int64]chan cdpResponse
|
||||
pendMu sync.Mutex
|
||||
closed bool
|
||||
conn net.Conn
|
||||
reader *bufio.Reader
|
||||
mu sync.Mutex
|
||||
nextID atomic.Int64
|
||||
port int
|
||||
pid int
|
||||
pending map[int64]chan cdpResponse
|
||||
pendMu sync.Mutex
|
||||
closed bool
|
||||
handlers map[string][]EventHandler
|
||||
hMu sync.Mutex
|
||||
}
|
||||
|
||||
type cdpRequest struct {
|
||||
@@ -245,7 +252,8 @@ func (c *CDPConn) sendCDP(method string, params map[string]any) (map[string]any,
|
||||
return resp.Result, nil
|
||||
}
|
||||
|
||||
// readLoop lee mensajes del WebSocket y los enruta a los canales pendientes.
|
||||
// readLoop lee mensajes del WebSocket y los enruta a los canales pendientes
|
||||
// (respuestas a comandos) o a los handlers registrados (eventos CDP).
|
||||
// Debe ejecutarse en una goroutine.
|
||||
func (c *CDPConn) readLoop() {
|
||||
for {
|
||||
@@ -277,9 +285,51 @@ func (c *CDPConn) readLoop() {
|
||||
if ok {
|
||||
ch <- resp
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Sin ID = evento CDP. Llamar handlers registrados para ese metodo.
|
||||
if resp.Method != "" {
|
||||
c.hMu.Lock()
|
||||
hs := append([]EventHandler(nil), c.handlers[resp.Method]...)
|
||||
c.hMu.Unlock()
|
||||
for _, h := range hs {
|
||||
// Aislamos panics de handlers ajenos para que un handler
|
||||
// roto no mate la conexion entera.
|
||||
func(h EventHandler) {
|
||||
defer func() { _ = recover() }()
|
||||
h(resp.Method, resp.Params)
|
||||
}(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OnEvent registra un handler para un metodo CDP (ej "Network.requestWillBeSent").
|
||||
// Devuelve una funcion `cancel` que des-registra el handler. Multiples handlers
|
||||
// para el mismo metodo se invocan en orden de registro.
|
||||
//
|
||||
// El handler corre en la goroutine de lectura — mantenlo rapido. Para trabajo
|
||||
// pesado, despacha a un canal/goroutine propios.
|
||||
func (c *CDPConn) OnEvent(method string, h EventHandler) (cancel func()) {
|
||||
if c == nil || h == nil || method == "" {
|
||||
return func() {}
|
||||
}
|
||||
c.hMu.Lock()
|
||||
if c.handlers == nil {
|
||||
c.handlers = make(map[string][]EventHandler)
|
||||
}
|
||||
c.handlers[method] = append(c.handlers[method], h)
|
||||
idx := len(c.handlers[method]) - 1
|
||||
c.hMu.Unlock()
|
||||
|
||||
return func() {
|
||||
c.hMu.Lock()
|
||||
defer c.hMu.Unlock()
|
||||
hs := c.handlers[method]
|
||||
if idx < len(hs) {
|
||||
c.handlers[method] = append(hs[:idx], hs[idx+1:]...)
|
||||
}
|
||||
// Si no tiene ID, es un evento CDP — por ahora los ignoramos
|
||||
// Las funciones que necesiten eventos usan polling o envian el comando y esperan
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user