Skip to content

Commit 7872d2f

Browse files
committed
fix: Skip function properties during diff comparison
When comparing VNode properties during diff, we were trying to compare function values directly (renderUpdate callback). Functions aren't comparable in Go, causing a panic: 'comparing uncomparable type func(float64, interface {})' **Fix:** - Added isFunction() helper to detect function properties - Modified propsChanged() to skip function properties during comparison - Only count and compare non-function properties **Related:** - dom.go already skips functions when setting DOM attributes - eventsChanged() already handles non-comparable event handlers similarly This allows GPURenderUpdate and other function callbacks to work correctly without causing panics during re-renders.
1 parent 76953ba commit 7872d2f

1 file changed

Lines changed: 33 additions & 1 deletion

File tree

pkg/runtime/diff.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,30 @@ func attrsChanged(old, new map[string]string) bool {
309309
}
310310

311311
func propsChanged(old, new map[string]interface{}) bool {
312-
if len(old) != len(new) {
312+
// Count non-function properties for length comparison
313+
oldCount := 0
314+
newCount := 0
315+
for _, v := range old {
316+
if !isFunction(v) {
317+
oldCount++
318+
}
319+
}
320+
for _, v := range new {
321+
if !isFunction(v) {
322+
newCount++
323+
}
324+
}
325+
326+
if oldCount != newCount {
313327
return true
314328
}
315329

316330
for k, v := range old {
331+
// Skip function properties - they can't be compared
332+
if isFunction(v) {
333+
continue
334+
}
335+
317336
if newV, exists := new[k]; !exists || newV != v {
318337
return true
319338
}
@@ -322,6 +341,19 @@ func propsChanged(old, new map[string]interface{}) bool {
322341
return false
323342
}
324343

344+
// isFunction checks if a value is a function type
345+
func isFunction(v interface{}) bool {
346+
if v == nil {
347+
return false
348+
}
349+
switch v.(type) {
350+
case func(float64, interface{}), func(*GPUCanvas), func(*GPUCanvas, float64):
351+
return true
352+
default:
353+
return false
354+
}
355+
}
356+
325357
func eventsChanged(old, new map[string]EventHandler) bool {
326358
// Event handlers are closures and can't be compared directly
327359
// Only return true if the event keys differ (events added/removed)

0 commit comments

Comments
 (0)