5b10b419a2
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.5 KiB
Go
84 lines
2.5 KiB
Go
package browser
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// CdpEvalInFrame ejecuta una expresion JavaScript en el contexto aislado de un iframe
|
|
// especifico usando Page.createIsolatedWorld + Runtime.evaluate con el contextId del frame.
|
|
// Retorna el resultado serializado como string.
|
|
func CdpEvalInFrame(c *CDPConn, frameID, expression string) (string, error) {
|
|
if c == nil {
|
|
return "", fmt.Errorf("cdp eval in frame: conexion nula")
|
|
}
|
|
if frameID == "" {
|
|
return "", fmt.Errorf("cdp eval in frame: frameID vacio")
|
|
}
|
|
|
|
// Page.enable es idempotente; necesario antes de crear mundos aislados
|
|
if _, err := c.sendCDP("Page.enable", nil); err != nil {
|
|
return "", fmt.Errorf("cdp eval in frame: Page.enable: %w", err)
|
|
}
|
|
|
|
// Crear un mundo aislado en el frame indicado para no contaminar su contexto JS
|
|
ctxRes, err := c.sendCDP("Page.createIsolatedWorld", map[string]any{
|
|
"frameId": frameID,
|
|
"worldName": "fn_registry_isolated",
|
|
"grantUniveralAccess": false,
|
|
})
|
|
if err != nil {
|
|
return "", fmt.Errorf("cdp eval in frame: createIsolatedWorld: %w", err)
|
|
}
|
|
|
|
ctxIDRaw, ok := ctxRes["executionContextId"]
|
|
if !ok {
|
|
return "", fmt.Errorf("cdp eval in frame: executionContextId no encontrado en respuesta")
|
|
}
|
|
ctxID, ok := ctxIDRaw.(float64)
|
|
if !ok {
|
|
return "", fmt.Errorf("cdp eval in frame: executionContextId tipo inesperado: %T", ctxIDRaw)
|
|
}
|
|
|
|
// Evaluar la expresion en el contexto aislado del frame
|
|
evRes, err := c.sendCDP("Runtime.evaluate", map[string]any{
|
|
"expression": expression,
|
|
"contextId": int(ctxID),
|
|
"returnByValue": true,
|
|
"awaitPromise": true,
|
|
})
|
|
if err != nil {
|
|
return "", fmt.Errorf("cdp eval in frame: Runtime.evaluate: %w", err)
|
|
}
|
|
|
|
// Verificar excepcion JS
|
|
if exc, ok := evRes["exceptionDetails"]; ok && exc != nil {
|
|
excMap, _ := exc.(map[string]any)
|
|
text, _ := excMap["text"].(string)
|
|
return "", fmt.Errorf("cdp eval in frame: excepcion JS en frame %q: %s", frameID, text)
|
|
}
|
|
|
|
// Extraer valor del resultado (mismo patron que CdpEvaluate)
|
|
resVal, ok := evRes["result"].(map[string]any)
|
|
if !ok {
|
|
return "", fmt.Errorf("cdp eval in frame: resultado inesperado: %v", evRes)
|
|
}
|
|
|
|
value, ok := resVal["value"]
|
|
if !ok {
|
|
// undefined u otro tipo no serializable
|
|
typ, _ := resVal["type"].(string)
|
|
return typ, nil
|
|
}
|
|
|
|
// Strings tal cual; objetos/arrays JS a JSON real (no la repr de Go de "%v").
|
|
if s, ok := value.(string); ok {
|
|
return s, nil
|
|
}
|
|
b, err := json.Marshal(value)
|
|
if err != nil {
|
|
return fmt.Sprintf("%v", value), nil
|
|
}
|
|
return string(b), nil
|
|
}
|