Skip to content

Conversation

benceruleanlu
Copy link
Member

@benceruleanlu benceruleanlu commented Oct 3, 2025

Implements droponcanvas functionality and a linkconnectoradapter refactor.

  • Drop on canvas (Shift and default) integrated via LinkConnector ‘dropped-on-canvas’ with proper CanvasPointerEvent.
  • LinkConnector adapter: now wraps the live canvas linkConnector (no duplicate state); added dropOnCanvas() helper.
  • Tests: Playwright scenarios for Shift-drop context menu/searchbox, pinned endpoint, type prefilter, and post-selection auto-connect (browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts).

There are some followup PRs that will fix/refactor some more noncritical things, like the terrible slotid, the number/string nodeid confusion, etc.

#5898 <-- #5903

@benceruleanlu benceruleanlu changed the title Vue Nodes: drop-on-canvas + pinned endpoint; adapter consolidation; tests Implement drop-on-canvas + linkconnectoradapter consolidation Oct 3, 2025
Copy link

github-actions bot commented Oct 3, 2025

🎭 Playwright Test Results

Some tests failed

⏰ Completed at: 10/03/2025, 11:35:16 AM UTC

📈 Summary

  • Total Tests: 483
  • Passed: 442 ✅
  • Failed: 6 ❌
  • Flaky: 5 ⚠️
  • Skipped: 30 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 433 / ❌ 6 / ⚠️ 5 / ⏭️ 30
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 6 / ❌ 0 / ⚠️ 0 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

@benceruleanlu benceruleanlu marked this pull request as ready for review October 3, 2025 03:15
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Oct 3, 2025
@benceruleanlu benceruleanlu added the New Browser Test Expectations New browser test screenshot should be set by github action label Oct 3, 2025
@christian-byrne christian-byrne added the claude-review Add to trigger a PR code review from Claude Code label Oct 3, 2025
y: number
}

const pointerHistory = new Map<number, PointerOffsets>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[performance] medium Priority

Issue: Pointer history map grows unbounded without cleanup of stale entries
Context: pointerHistory Map on line 13 accumulates entries for all pointer IDs but only explicitly cleans up when clearCanvasPointerHistory is called, which may not happen for all pointers
Suggestion: Add periodic cleanup or use WeakMap if possible, or implement automatic cleanup in pointerup/pointercancel events

event.clientY
])

const canvas = useCanvasStore().getCanvas()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[quality] low Priority

Issue: Potential undefined canvas access without null check
Context: useCanvasStore().getCanvas() could return undefined, then accessing .ds property would throw
Suggestion: Add null check: const canvas = useCanvasStore().getCanvas(); if (!canvas) return defaultEnhancement;

if (cached != null) {
candidate.compatible = cached
} else {
const nodeId = Number(layout.nodeId)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[quality] medium Priority

Issue: Inconsistent nodeId types - mixing string and number conversions
Context: Layout.nodeId is string (line 34) but converted to number for graph.getNodeById calls throughout the codebase
Suggestion: Establish consistent type discipline - either use NodeId type consistently or create utility functions for safe conversion

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is something I'm working on to fix, it's scuffed right now but works, it's because of the terrible group node code that forces it to be number or string type

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is something I'm working on to fix, it's scuffed right now but works, it's because of the terrible group node code that forces it to be number or string type


if (!adapter || !graph) return null

const nodeId = Number(nodeIdStr)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[quality] medium Priority

Issue: No validation that Number() conversion succeeded before using nodeId
Context: Number(layout.nodeId) could return NaN if layout.nodeId contains non-numeric data, which would cause graph.getNodeById to fail silently
Suggestion: Add validation: const nodeId = Number(layout.nodeId); if (isNaN(nodeId)) return null;

Copy link
Contributor

@christian-byrne christian-byrne Oct 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We technically support string-based node IDs (like "nodeName") if you look at the backend code - esp. for subgraphs or virtual nodes on the backend IIRC.

import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'
import { app } from '@/scripts/app'

// Keep one adapter per graph so rendering and interaction share state.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[architecture] low Priority

Issue: WeakMap usage might cause adapter recreation if LGraph is temporarily dereferenced
Context: WeakMap allows garbage collection which could cause adapter recreation, potentially breaking the singleton pattern intended by the comment above
Suggestion: Consider if explicit cleanup on graph destruction would be more predictable than relying on GC

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that happens i think that should be fixed and not making this more resilient


app.canvas?.setDirty(true, true)
}
const raf = createRafBatch(processPointerMoveFrame)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[performance] medium Priority

Issue: Heavy computation in RAF callback could cause frame drops
Context: processPointerMoveFrame performs expensive DOM queries, layout lookups, and cache operations on every animation frame
Suggestion: Consider debouncing DOM queries or pre-caching hover targets to reduce per-frame work

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, let me recheck perf

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comprehensive PR Review

This review is generated by Claude. It may not always be accurate, as with human reviewers. If you believe that any of the comments are invalid or incorrect, please state why for each. For others, please implement the changes in one way or another.

Review Summary

PR: Implement drop-on-canvas + linkconnectoradapter consolidation (#5898)
Impact: 469 additions, 240 deletions across 15 files

Issue Distribution

  • Critical: 0
  • High: 0
  • Medium: 4
  • Low: 3

Category Breakdown

  • Architecture: 1 issues
  • Security: 0 issues
  • Performance: 2 issues
  • Code Quality: 4 issues

Key Findings

Architecture & Design

This PR implements a significant refactor of the link interaction system with good architectural principles:

  • LinkConnectorAdapter consolidation: Good move to eliminate duplicate state by wrapping the live canvas linkConnector rather than creating new instances
  • Drop orchestrator pattern: Clean separation of concerns with specialized functions for slot and node surface candidate resolution
  • Canvas pointer event abstraction: Well-designed abstraction for canvas coordinate conversion and pointer history

The WeakMap usage for adapter caching follows a reasonable pattern, though the garbage collection behavior might cause unexpected adapter recreation.

Performance Impact

The RAF-based pointer movement processing is well-architected but could benefit from optimization:

  • Heavy DOM querying operations on every animation frame
  • Unbounded pointer history growth without cleanup mechanisms
  • Consider debouncing expensive operations or pre-caching hover targets

Bundle impact appears minimal with mostly refactoring existing functionality.

Integration Points

  • Backward compatibility: Preserved existing Vue composable behavior patterns
  • Extension compatibility: Maintained existing public APIs that extensions depend on
  • Test coverage: Excellent Playwright test coverage for the new shift-drop functionality

Positive Observations

  • Comprehensive E2E test coverage including edge cases and error scenarios
  • Clean TypeScript interfaces and proper type safety throughout
  • Good use of caching patterns to avoid repeated expensive operations
  • Proper cleanup patterns with pointer history management
  • Well-structured composable following Vue 3 best practices

References

  • Repository Architecture Guide
  • Vue 3 Composition API patterns
  • ComfyUI Frontend Guidelines (CLAUDE.md)

Next Steps

  1. Address medium priority issues for better robustness (pointer history cleanup, number validation)
  2. Consider performance optimizations for RAF callbacks
  3. Validate comprehensive test coverage passes
  4. Consider documenting the event propagation patterns

This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review.

@benceruleanlu
Copy link
Member Author

@codex review

Copy link

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:links area:vue-migration claude-review Add to trigger a PR code review from Claude Code New Browser Test Expectations New browser test screenshot should be set by github action size:XL This PR changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants