feat(webview): console watcher additions + canonical type normalisation
Spark draft + opus-style fixes during integration: - normalizeConsoleType applied consistently across FormatConsoleOutput + Errors/ErrorsAll + Warnings/WarningsAll iterators — previously raw "warning" inputs missed the "warn" comparisons silently - core.Trim instead of non-existent core.TrimSpace Spark feature work preserved (Errors/Warnings iterators, formatted console output, type normalisation helper). Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
a6304b8e29
commit
7a4450cf9f
2 changed files with 117 additions and 33 deletions
116
console.go
116
console.go
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"iter"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
|
@ -55,6 +56,93 @@ func NewConsoleWatcher(wv *Webview) *ConsoleWatcher {
|
|||
return cw
|
||||
}
|
||||
|
||||
// normalizeConsoleType converts CDP event types to package-level values.
|
||||
func normalizeConsoleType(raw string) string {
|
||||
normalized := strings.ToLower(core.Trim(core.Sprint(raw)))
|
||||
switch normalized {
|
||||
case "warning":
|
||||
return "warn"
|
||||
default:
|
||||
return normalized
|
||||
}
|
||||
}
|
||||
|
||||
// consoleTextFromArgs extracts message text from Runtime.consoleAPICalled args.
|
||||
func consoleTextFromArgs(args []any) string {
|
||||
text := core.NewBuilder()
|
||||
for i, arg := range args {
|
||||
if i > 0 {
|
||||
text.WriteString(" ")
|
||||
}
|
||||
text.WriteString(consoleArgText(arg))
|
||||
}
|
||||
|
||||
return text.String()
|
||||
}
|
||||
|
||||
func consoleArgText(arg any) string {
|
||||
remoteObj, ok := arg.(map[string]any)
|
||||
if !ok {
|
||||
return consoleValueToString(arg)
|
||||
}
|
||||
|
||||
if value, ok := remoteObj["value"]; ok {
|
||||
return consoleValueToString(value)
|
||||
}
|
||||
|
||||
if desc, ok := remoteObj["description"].(string); ok && desc != "" {
|
||||
return desc
|
||||
}
|
||||
|
||||
if preview, ok := remoteObj["preview"].(map[string]any); ok {
|
||||
if description, ok := preview["description"].(string); ok && description != "" {
|
||||
return description
|
||||
}
|
||||
}
|
||||
|
||||
if preview, ok := remoteObj["preview"].(map[string]any); ok {
|
||||
if value, ok := preview["value"].(string); ok && value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
if r := core.JSONMarshal(remoteObj); r.OK {
|
||||
if encoded, ok := r.Value.([]byte); ok {
|
||||
return string(encoded)
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func consoleValueToString(value any) string {
|
||||
if value == nil {
|
||||
return "null"
|
||||
}
|
||||
if valueStr, ok := value.(string); ok {
|
||||
return valueStr
|
||||
}
|
||||
|
||||
if r := core.JSONMarshal(value); r.OK {
|
||||
if encoded, ok := r.Value.([]byte); ok {
|
||||
return string(encoded)
|
||||
}
|
||||
}
|
||||
|
||||
return core.Sprint(value)
|
||||
}
|
||||
|
||||
func consoleMessageTimestamp(params map[string]any) time.Time {
|
||||
timestamp, ok := params["timestamp"].(float64)
|
||||
if !ok {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
seconds := int64(timestamp)
|
||||
nanoseconds := int64((timestamp - float64(seconds)) * float64(time.Second))
|
||||
return time.Unix(seconds, nanoseconds).UTC()
|
||||
}
|
||||
|
||||
// AddFilter adds a filter to the watcher.
|
||||
func (cw *ConsoleWatcher) AddFilter(filter ConsoleFilter) {
|
||||
cw.mu.Lock()
|
||||
|
|
@ -156,7 +244,7 @@ func (cw *ConsoleWatcher) ErrorsAll() iter.Seq[ConsoleMessage] {
|
|||
defer cw.mu.RUnlock()
|
||||
|
||||
for _, msg := range cw.messages {
|
||||
if msg.Type == "error" {
|
||||
if normalizeConsoleType(msg.Type) == "error" {
|
||||
if !yield(msg) {
|
||||
return
|
||||
}
|
||||
|
|
@ -177,7 +265,7 @@ func (cw *ConsoleWatcher) WarningsAll() iter.Seq[ConsoleMessage] {
|
|||
defer cw.mu.RUnlock()
|
||||
|
||||
for _, msg := range cw.messages {
|
||||
if msg.Type == "warning" {
|
||||
if normalizeConsoleType(msg.Type) == "warn" {
|
||||
if !yield(msg) {
|
||||
return
|
||||
}
|
||||
|
|
@ -268,21 +356,11 @@ func (cw *ConsoleWatcher) ErrorCount() int {
|
|||
|
||||
// handleConsoleEvent processes incoming console events.
|
||||
func (cw *ConsoleWatcher) handleConsoleEvent(params map[string]any) {
|
||||
msgType, _ := params["type"].(string)
|
||||
msgType := normalizeConsoleType(core.Sprint(params["type"]))
|
||||
|
||||
// Extract args
|
||||
args, _ := params["args"].([]any)
|
||||
text := core.NewBuilder()
|
||||
for i, arg := range args {
|
||||
if argMap, ok := arg.(map[string]any); ok {
|
||||
if val, ok := argMap["value"]; ok {
|
||||
if i > 0 {
|
||||
text.WriteString(" ")
|
||||
}
|
||||
text.WriteString(core.Sprint(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
text := consoleTextFromArgs(args)
|
||||
|
||||
// Extract stack trace info
|
||||
stackTrace, _ := params["stackTrace"].(map[string]any)
|
||||
|
|
@ -300,8 +378,8 @@ func (cw *ConsoleWatcher) handleConsoleEvent(params map[string]any) {
|
|||
|
||||
msg := ConsoleMessage{
|
||||
Type: msgType,
|
||||
Text: text.String(),
|
||||
Timestamp: time.Now(),
|
||||
Text: text,
|
||||
Timestamp: consoleMessageTimestamp(params),
|
||||
URL: url,
|
||||
Line: line,
|
||||
Column: column,
|
||||
|
|
@ -346,7 +424,7 @@ func (cw *ConsoleWatcher) matchesFilter(msg ConsoleMessage) bool {
|
|||
|
||||
// matchesSingleFilter checks if a message matches a specific filter.
|
||||
func (cw *ConsoleWatcher) matchesSingleFilter(msg ConsoleMessage, filter ConsoleFilter) bool {
|
||||
if filter.Type != "" && msg.Type != filter.Type {
|
||||
if filter.Type != "" && msg.Type != normalizeConsoleType(filter.Type) {
|
||||
return false
|
||||
}
|
||||
if filter.Pattern != "" {
|
||||
|
|
@ -572,10 +650,10 @@ func FormatConsoleOutput(messages []ConsoleMessage) string {
|
|||
output := core.NewBuilder()
|
||||
for _, msg := range messages {
|
||||
prefix := ""
|
||||
switch msg.Type {
|
||||
switch normalizeConsoleType(msg.Type) {
|
||||
case "error":
|
||||
prefix = "[ERROR]"
|
||||
case "warning":
|
||||
case "warn":
|
||||
prefix = "[WARN]"
|
||||
case "info":
|
||||
prefix = "[INFO]"
|
||||
|
|
|
|||
34
webview.go
34
webview.go
|
|
@ -363,6 +363,10 @@ func (wv *Webview) SetViewport(width, height int) error {
|
|||
"deviceScaleFactor": 1,
|
||||
"mobile": false,
|
||||
})
|
||||
if err != nil {
|
||||
return coreerr.E("Webview.SetViewport", "failed to set viewport", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -374,6 +378,10 @@ func (wv *Webview) SetUserAgent(userAgent string) error {
|
|||
_, err := wv.client.Call(ctx, "Emulation.setUserAgentOverride", map[string]any{
|
||||
"userAgent": userAgent,
|
||||
})
|
||||
if err != nil {
|
||||
return coreerr.E("Webview.SetUserAgent", "failed to set user agent", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -398,6 +406,10 @@ func (wv *Webview) GoBack() error {
|
|||
_, err := wv.client.Call(ctx, "Page.goBackOrForward", map[string]any{
|
||||
"delta": -1,
|
||||
})
|
||||
if err != nil {
|
||||
return coreerr.E("Webview.GoBack", "failed to go back", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -409,6 +421,10 @@ func (wv *Webview) GoForward() error {
|
|||
_, err := wv.client.Call(ctx, "Page.goBackOrForward", map[string]any{
|
||||
"delta": 1,
|
||||
})
|
||||
if err != nil {
|
||||
return coreerr.E("Webview.GoForward", "failed to go forward", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -458,21 +474,11 @@ func (wv *Webview) enableConsole() error {
|
|||
|
||||
// handleConsoleEvent processes console API events.
|
||||
func (wv *Webview) handleConsoleEvent(params map[string]any) {
|
||||
msgType, _ := params["type"].(string)
|
||||
msgType := normalizeConsoleType(core.Sprint(params["type"]))
|
||||
|
||||
// Extract args
|
||||
args, _ := params["args"].([]any)
|
||||
text := core.NewBuilder()
|
||||
for i, arg := range args {
|
||||
if argMap, ok := arg.(map[string]any); ok {
|
||||
if val, ok := argMap["value"]; ok {
|
||||
if i > 0 {
|
||||
text.WriteString(" ")
|
||||
}
|
||||
text.WriteString(core.Sprint(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
text := consoleTextFromArgs(args)
|
||||
|
||||
// Extract stack trace info
|
||||
stackTrace, _ := params["stackTrace"].(map[string]any)
|
||||
|
|
@ -490,8 +496,8 @@ func (wv *Webview) handleConsoleEvent(params map[string]any) {
|
|||
|
||||
wv.addConsoleMessage(ConsoleMessage{
|
||||
Type: msgType,
|
||||
Text: text.String(),
|
||||
Timestamp: time.Now(),
|
||||
Text: text,
|
||||
Timestamp: consoleMessageTimestamp(params),
|
||||
URL: url,
|
||||
Line: line,
|
||||
Column: column,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue