Added MaskEditor Rotate and Mirror Functions#7841
Conversation
📝 WalkthroughWalkthroughAdds rotate (left/right) and mirror (horizontal/vertical) actions to the mask editor UI; implements Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant TopBar as TopBarHeader
participant Transform as useCanvasTransform
participant Store as maskEditorStore
participant Brush as useBrushDrawing
participant GPU as GPU
User->>TopBar: Click rotate/mirror
TopBar->>Transform: invoke rotate/mirror method
Transform->>Transform: read mask/rgb/img pixels, apply transform, premultiply, swap dims if needed, save history
Transform->>Store: set gpuTexturesNeedRecreation, gpuTextureWidth/Height, pending GPU buffers
Store->>Brush: gpuTexturesNeedRecreation watcher triggers
Brush->>GPU: destroy/create/upload textures with new size (or upload pending buffers)
GPU-->>Brush: confirm textures
Brush->>Store: clear gpu recreation flags and pending buffers
Brush->>User: updated canvases displayed
Possibly related PRs
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🎭 Playwright Test Results⏰ Completed at: 01/10/2026, 01:49:54 PM UTC 📈 Summary
📊 Test Reports by Browser
🎉 Click on the links above to view detailed test results for each browser configuration. |
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 3.26 MB (baseline 3.25 MB) • 🔴 +18.5 kBMain entry bundles and manifests
Status: 3 added / 3 removed Graph Workspace — 1.05 MB (baseline 1.05 MB) • 🔴 +392 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 6.63 kB (baseline 6.63 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 1 added / 1 removed Panels & Settings — 337 kB (baseline 337 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 6 added / 6 removed UI Components — 199 kB (baseline 199 kB) • ⚪ 0 BReusable component library chunks
Status: 8 added / 8 removed Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 2 added / 2 removed Utilities & Hooks — 1.41 kB (baseline 1.41 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 1 added / 1 removed Vendor & Third-Party — 9.19 MB (baseline 9.19 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 4.73 MB (baseline 4.73 MB) • ⚪ 0 BBundles that do not match a named category
Status: 16 added / 16 removed |
There was a problem hiding this comment.
Actionable comments posted: 7
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useBrushDrawing.tssrc/composables/maskeditor/useCanvasTransform.tssrc/locales/en/main.jsonsrc/stores/maskEditorStore.ts
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.ts
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3.5+ with TypeScript in.vuefiles, exclusively using Composition API with<script setup lang="ts">syntax
Use Tailwind 4 for styling in Vue components; avoid<style>blocks
Name Vue components using PascalCase (e.g.,MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not usewithDefaultsor runtime props declaration
Prefercomputed()overrefwithwatchwhen deriving values
PreferuseModelover separately defining prop and emit for two-way binding
Usevue-i18nin composition API for string literals; place new translation entries insrc/locales/en/main.json
Usecn()utility function from@/utils/tailwindUtilfor merging Tailwind class names; do not use:class="[]"syntax
Do not use thedark:Tailwind variant; use semantic values from thestyle.csstheme instead (e.g.,bg-node-component-surface)
Do not use!importantor the!important prefix for Tailwind classes; find and correct interfering!importantclasses instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.tssrc/locales/en/main.json
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.ts
**/**/use[A-Z]*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables using the pattern
useXyz.ts
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Minimize the surface area (exported values) of each module and composable
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
src/**/stores/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores
Files:
src/stores/maskEditorStore.ts
**/*Store.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name Pinia stores using the pattern
*Store.ts
Files:
src/stores/maskEditorStore.ts
🧠 Learnings (19)
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles in Vue components
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T16:03:02.066Z
Learnt from: henrikvilhelmberglund
Repo: Comfy-Org/ComfyUI_frontend PR: 7617
File: src/components/actionbar/ComfyActionbar.vue:301-308
Timestamp: 2025-12-18T16:03:02.066Z
Learning: In the ComfyUI frontend queue system, useQueuePendingTaskCountStore().count indicates the number of tasks in the queue, where count = 1 means a single active/running task and count > 1 means there are pending tasks in addition to the active task. Therefore, in src/components/actionbar/ComfyActionbar.vue, enable the 'Clear Pending Tasks' button only when count > 1 to avoid clearing the currently running task. The active task should be canceled using the 'Cancel current run' button instead. This rule should be enforced via a conditional check on the queue count, with appropriate disabled/aria-disabled states for accessibility, and tests should verify behavior for count = 1 and count > 1.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useBrushDrawing.tssrc/stores/maskEditorStore.ts
🧬 Code graph analysis (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
src/stores/maskEditorStore.ts (1)
useMaskEditorStore(19-301)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: lint-and-format
- GitHub Check: collect
🔇 Additional comments (4)
src/locales/en/main.json (1)
968-971: LGTM!The new localization keys for rotation and mirroring operations are clear, well-named, and follow the existing conventions. The placement after the
redoentry is logical.src/stores/maskEditorStore.ts (1)
221-226: LGTM!The reset logic for GPU-related state is comprehensive and properly clears all flags and pending data. This ensures clean state transitions and prevents memory leaks from retained ArrayBuffers.
src/composables/maskeditor/useCanvasTransform.ts (2)
108-115: Premultiplication logic is correct.The alpha premultiplication implementation correctly converts from straight alpha (used by Canvas 2D) to premultiplied alpha (required by WebGPU). The formula
color = color * alphais applied per-channel with proper rounding.
221-253: LGTM! Mirror operations maintain canvas dimensions correctly.The mirroring logic correctly:
- Maintains original canvas dimensions (no swap needed)
- Applies transformations to all three layers (mask, rgb, img)
- Triggers GPU texture updates with unchanged dimensions
- Saves the result to history for undo/redo support
The implementation is clean and follows the same pattern as rotation operations.
There was a problem hiding this comment.
Actionable comments posted: 7
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
src/components/maskeditor/MaskEditorContent.vuesrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useBrushDrawing.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/composables/useCoreCommands.tssrc/extensions/core/maskeditor.tssrc/stores/maskEditorStore.ts
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
**/**/use[A-Z]*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables using the pattern
useXyz.ts
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Minimize the surface area (exported values) of each module and composable
Files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3.5+ with TypeScript in.vuefiles, exclusively using Composition API with<script setup lang="ts">syntax
Use Tailwind 4 for styling in Vue components; avoid<style>blocks
Name Vue components using PascalCase (e.g.,MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not usewithDefaultsor runtime props declaration
Prefercomputed()overrefwithwatchwhen deriving values
PreferuseModelover separately defining prop and emit for two-way binding
Usevue-i18nin composition API for string literals; place new translation entries insrc/locales/en/main.json
Usecn()utility function from@/utils/tailwindUtilfor merging Tailwind class names; do not use:class="[]"syntax
Do not use thedark:Tailwind variant; use semantic values from thestyle.csstheme instead (e.g.,bg-node-component-surface)
Do not use!importantor the!important prefix for Tailwind classes; find and correct interfering!importantclasses instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
src/**/stores/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/stores/**/*.{ts,tsx}: Maintain clear public interfaces and restrict extension access in stores
Use TypeScript for type safety in state management stores
Files:
src/stores/maskEditorStore.ts
**/*Store.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name Pinia stores using the pattern
*Store.ts
Files:
src/stores/maskEditorStore.ts
🧠 Learnings (35)
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Prefer `computed()` over `ref` with `watch` when deriving values
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use watch and watchEffect for side effects
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-12-04T21:43:49.363Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/parameters/TabParameters.vue:10-0
Timestamp: 2025-12-04T21:43:49.363Z
Learning: Vue 3.5+ supports reactive props destructure in <script setup>. Destructuring props directly (e.g., `const { nodes } = defineProps<{ nodes: LGraphNode[] }>()`) maintains reactivity through compiler transformation. This is the recommended modern approach and does not require using `props.x` or `toRef`/`toRefs`.
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement cleanup for async operations in Vue components
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles in Vue components
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Applied to files:
src/composables/maskeditor/useBrushDrawing.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useBrushDrawing.tssrc/composables/useCoreCommands.tssrc/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/components/maskeditor/MaskEditorContent.vuesrc/stores/maskEditorStore.tssrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-11T03:55:57.926Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-12-18T16:03:02.066Z
Learnt from: henrikvilhelmberglund
Repo: Comfy-Org/ComfyUI_frontend PR: 7617
File: src/components/actionbar/ComfyActionbar.vue:301-308
Timestamp: 2025-12-18T16:03:02.066Z
Learning: In the ComfyUI frontend queue system, useQueuePendingTaskCountStore().count indicates the number of tasks in the queue, where count = 1 means a single active/running task and count > 1 means there are pending tasks in addition to the active task. Therefore, in src/components/actionbar/ComfyActionbar.vue, enable the 'Clear Pending Tasks' button only when count > 1 to avoid clearing the currently running task. The active task should be canceled using the 'Cancel current run' button instead. This rule should be enforced via a conditional check on the queue count, with appropriate disabled/aria-disabled states for accessibility, and tests should verify behavior for count = 1 and count > 1.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/components/maskeditor/MaskEditorContent.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Check tests-ui/README.md for test guidelines
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.test.ts : Aim for behavioral coverage of critical and new features in unit tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Take advantage of `TypedArray` `subarray` when appropriate
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
🧬 Code graph analysis (1)
src/extensions/core/maskeditor.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-264)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
- GitHub Check: playwright-tests-chromium-sharded (4, 8)
- GitHub Check: playwright-tests-chromium-sharded (1, 8)
- GitHub Check: playwright-tests-chromium-sharded (3, 8)
- GitHub Check: playwright-tests-chromium-sharded (5, 8)
- GitHub Check: playwright-tests-chromium-sharded (7, 8)
- GitHub Check: playwright-tests-chromium-sharded (8, 8)
- GitHub Check: playwright-tests-chromium-sharded (6, 8)
- GitHub Check: playwright-tests-chromium-sharded (2, 8)
- GitHub Check: playwright-tests (chromium-0.5x)
- GitHub Check: playwright-tests (mobile-chrome)
- GitHub Check: playwright-tests (chromium-2x)
- GitHub Check: lint-and-format
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (17)
src/composables/useCoreCommands.ts (2)
63-65: LGTM! Clean integration with mask editor state.The imports are correctly added following the repository's pattern of keeping type imports separate from regular imports.
204-223: LGTM! Proper conditional routing for undo/redo commands.The implementation correctly routes undo/redo operations to the mask editor's history when the mask editor dialog is open, and falls back to the workflow change tracker otherwise. The pattern is clean and maintains separation of concerns.
src/composables/maskeditor/useBrushDrawing.ts (2)
1-1: LGTM! Proper WebGPU types reference.The triple-slash directive correctly enables WebGPU type definitions for this file.
237-357: LGTM! Race condition guard properly implemented.The
isRecreatingTexturesguard addresses the race condition concern from the previous review by preventing concurrent texture recreation. The implementation properly:
- Checks all preconditions including the guard flag
- Destroys old textures before creating new ones (addressing memory pressure concerns)
- Handles both pending data upload and canvas fallback scenarios
- Recreates readback buffers with correct dimensions
- Cleans up flags in a finally block ensuring proper state reset even on error
The fallback to
updateGPUFromCanvas()when pending data is null is reasonable, though it assumes canvas state is current.src/components/maskeditor/dialog/TopBarHeader.vue (2)
38-102: LGTM! Clean UI implementation with proper visual separation.The four new transformation buttons (rotate left/right, mirror horizontal/vertical) are well-integrated with:
- Consistent styling using
iconButtonClass- Clear SVG icons for each action
- Proper tooltips using i18n keys
- Visual separators (dividers) between control groups for better UX
161-191: LGTM! Error handling properly implemented.The transformation handlers correctly implement try-catch error handling as requested in the previous review. Each handler:
- Awaits the async transformation operation
- Logs errors to console with clear context
- Prevents unhandled promise rejections
This addresses the past review comment about adding error handling to transformation handlers.
src/composables/maskeditor/useCanvasHistory.ts (4)
4-9: Well-structured interface for three-layer state.The
CanvasStateinterface cleanly captures all three canvas layers (mask, rgb, img) with appropriate union type supporting bothImageDataandImageBitmap. This enables efficient history management for rotation operations that produceImageBitmapinstances.
29-75: LGTM: Initialization logic correctly extended to three layers.The function properly validates all three canvas contexts and their dimensions before capturing state. The
requestAnimationFrameretry pattern handles async canvas initialization gracefully.
106-119: Verify the "all-or-nothing" requirement for provided data is intentional.The condition
if (providedMaskData && providedRgbData && providedImgData)requires all three data parameters to be provided together, otherwise fresh data is captured from all canvases. This ensures consistency but callers must supply all three or none.This design is correct for the current use case (transforms always produce all three), but consider adding a comment documenting this requirement.
166-177: Good memory management for ImageBitmap resources.The
cleanupStatefunction properly checksinstanceof ImageBitmapbefore callingclose(), ensuring GPU-backed resources are released. TheclearStatesfunction correctly iterates all states for cleanup before clearing the array.src/stores/maskEditorStore.ts (2)
226-232: GPU state reset is complete and consistent.All five GPU-related refs are properly reset to their initial values, ensuring clean state when the mask editor is reset.
279-284: GPU texture signals properly exposed for cross-module coordination.The exported refs enable
useCanvasTransformto signal texture recreation needs and provide data, whileuseBrushDrawingcan watch these signals to perform the actual GPU texture recreation. This decoupled design is appropriate.src/composables/maskeditor/useCanvasTransform.ts (5)
61-103: Mirror algorithm is correct.The coordinate transformations for mirroring are correct:
- Horizontal:
(x,y) → (width-1-x, y)- Vertical:
(x,y) → (x, height-1-y)Dimensions remain unchanged, and the index calculation correctly uses
width.
108-115: Premultiplication implementation is correct.Standard premultiplied alpha calculation:
R' = R * (A/255), etc. The in-place mutation is intentional for performance.
177-221: Rotation workflow is well-structured.The function correctly:
- Validates all canvas/context dependencies
- Captures original dimensions before transformation
- Rotates all three layers consistently
- Swaps canvas dimensions to match rotated data
- Applies rotated ImageData to canvases
- Conditionally recreates GPU textures
- Saves state to history for undo/redo support
The async/await pattern with
recreateGPUTexturesensures GPU operations complete before history save.
226-258: Mirror workflow correctly preserves dimensions.The function follows the same pattern as
rotateAllLayersbut correctly omits dimension swapping since mirroring doesn't change canvas size. GPU texture recreation and history save are handled appropriately.
260-263: Minimal API surface exposed.Only the two public operations are exported, keeping helper functions (
rotateCanvas,mirrorCanvas,premultiplyData,recreateGPUTextures) as private implementation details. This follows the guideline to minimize exported surface area.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
160-165: Remove commented-out code.Commented code should not remain in production. Either enable this defensive check or remove it entirely.
🔎 Option 1: Enable the check (recommended)
- /* - if (maskData.buffer instanceof SharedArrayBuffer || rgbData.buffer instanceof SharedArrayBuffer) { - console.error('[useCanvasTransform] SharedArrayBuffer detected, WebGPU writeTexture will fail') - return - } - */ + if (maskData.buffer instanceof SharedArrayBuffer || rgbData.buffer instanceof SharedArrayBuffer) { + console.error('[useCanvasTransform] SharedArrayBuffer detected, WebGPU writeTexture will fail') + return + }🔎 Option 2: Remove commented code
- /* - if (maskData.buffer instanceof SharedArrayBuffer || rgbData.buffer instanceof SharedArrayBuffer) { - console.error('[useCanvasTransform] SharedArrayBuffer detected, WebGPU writeTexture will fail') - return - } - */
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
🧰 Additional context used
📓 Path-based instructions (11)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
**/**/use[A-Z]*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables using the pattern
useXyz.ts
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Minimize the surface area (exported values) of each module and composable
Files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
🧠 Learnings (8)
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Take advantage of `TypedArray` `subarray` when appropriate
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasTransform.tssrc/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/composables/maskeditor/useCanvasHistory.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: lint-and-format
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (14)
src/composables/maskeditor/useCanvasTransform.ts (8)
1-8: LGTM: Clean composable structure.The composable setup follows proper conventions with the store access at the top level.
12-56: Rotation logic is mathematically correct.The coordinate transformations are accurate:
- Clockwise 90°:
(x,y) → (height-1-y, x)- Counter-clockwise 90°:
(x,y) → (y, width-1-x)The destination index calculation correctly uses
heightas the new row width since dimensions are swapped.Per coding guidelines, prefer function declarations over function expressions for pure functions. However, since these are internal helpers with consistent patterns throughout the file, this is acceptable.
61-103: Mirror logic is correct.The pixel mirroring transformations are accurate:
- Horizontal:
(x,y) → (width-1-x, y)- Vertical:
(x,y) → (x, height-1-y)The implementation maintains dimensions correctly and copies RGBA values properly.
108-115: Premultiplication logic is correct for GPU upload.Alpha premultiplication is properly applied in-place. The division by 255 and multiplication correctly converts straight alpha to premultiplied alpha format required by GPU pipelines.
121-133: Context validation is properly implemented.The guard clause correctly validates all required resources including
maskCtxandrgbCtx, addressing the previous concern about non-null assertions.
183-227: Rotation flow is well-structured.The method correctly:
- Validates all required canvases and contexts
- Captures original dimensions before transformation
- Rotates all three layers consistently
- Swaps canvas dimensions appropriately
- Applies rotated data back to canvases
- Triggers GPU texture recreation when needed
- Saves state to history for undo/redo support
232-264: Mirror flow correctly preserves dimensions.Unlike rotation, mirroring maintains the original dimensions while transforming pixel data. The implementation correctly handles GPU texture updates (data changes, not dimensions) and history recording.
266-269: Minimal public API surface.Only
rotateAllLayersandmirrorAllLayersare exported, keeping internal helpers private. This aligns with the coding guideline to minimize the surface area of each module.src/composables/maskeditor/useCanvasHistory.ts (6)
4-9: Well-defined state interface.The
CanvasStateinterface clearly documents the three-layer structure and supports bothImageData(for direct pixel manipulation) andImageBitmap(for efficient storage/rendering).
77-132: Three-layer state management is correct.The
saveStatefunction properly:
- Validates all required contexts and canvases
- Handles both provided data and fresh captures
- Prunes redo history when new state is saved
- Maintains max history size with proper cleanup
134-144: Simplified undo/redo with early returns.The refactored
undoandredofunctions use clean early returns instead of alert dialogs, improving UX and code clarity.
174-188: Layer restoration handles both ImageBitmap and ImageData.The
forEachloop correctly distinguishes betweenImageBitmap(requiresclearRect+drawImage) andImageData(usesputImageData). This supports efficient storage while maintaining full restoration capability.
190-194: Proper ImageBitmap cleanup prevents memory leaks.The
cleanupStatehelper correctly calls.close()onImageBitmapinstances to release GPU resources. This aligns with the coding guideline to clean up subscriptions and resources.
196-201: clearStates properly cleans up all history.Using
forEach(cleanupState)ensures allImageBitmapresources are released before clearing the array, preventing memory leaks.
|
Thank you @trsommer. Just updated the rotate buttons with a different SVG for ease of interpretation.
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/components/maskeditor/dialog/TopBarHeader.vue
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3.5+ with TypeScript in.vuefiles, exclusively using Composition API with<script setup lang="ts">syntax
Use Tailwind 4 for styling in Vue components; avoid<style>blocks
Name Vue components using PascalCase (e.g.,MenuHamburger.vue)
Use Vue 3.5 TypeScript-style default prop declaration with reactive props destructuring; do not usewithDefaultsor runtime props declaration
Prefercomputed()overrefwithwatchwhen deriving values
PreferuseModelover separately defining prop and emit for two-way binding
Usevue-i18nin composition API for string literals; place new translation entries insrc/locales/en/main.json
Usecn()utility function from@/utils/tailwindUtilfor merging Tailwind class names; do not use:class="[]"syntax
Do not use thedark:Tailwind variant; use semantic values from thestyle.csstheme instead (e.g.,bg-node-component-surface)
Do not use!importantor the!important prefix for Tailwind classes; find and correct interfering!importantclasses instead
Avoid new usage of PrimeVue components; use VueUse, shadcn/vue, or Reka UI instead
Leverage VueUse functions for performance-enhancing styles in Vue components
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
🧠 Learnings (18)
📚 Learning: 2025-12-11T03:55:57.926Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Implement proper error handling in code
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles in Vue components
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T16:03:02.066Z
Learnt from: henrikvilhelmberglund
Repo: Comfy-Org/ComfyUI_frontend PR: 7617
File: src/components/actionbar/ComfyActionbar.vue:301-308
Timestamp: 2025-12-18T16:03:02.066Z
Learning: In the ComfyUI frontend queue system, useQueuePendingTaskCountStore().count indicates the number of tasks in the queue, where count = 1 means a single active/running task and count > 1 means there are pending tasks in addition to the active task. Therefore, in src/components/actionbar/ComfyActionbar.vue, enable the 'Clear Pending Tasks' button only when count > 1 to avoid clearing the currently running task. The active task should be canceled using the 'Cancel current run' button instead. This rule should be enforced via a conditional check on the queue count, with appropriate disabled/aria-disabled states for accessibility, and tests should verify behavior for count = 1 and count > 1.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (2)
src/components/maskeditor/dialog/TopBarHeader.vue (2)
134-134: LGTM! Proper composition API usage.The import and instantiation of
useCanvasTransformfollows the established pattern used foruseCanvasTools.Also applies to: 143-143
38-105: LGTM! Clean implementation of transform UI controls.The rotate and mirror buttons are well-integrated, following the existing patterns for undo/redo buttons. The visual separators provide clear grouping, and the inline SVG icons are consistent with the component's style. All required i18n keys (
maskEditor.rotateLeft,maskEditor.rotateRight,maskEditor.mirrorHorizontal,maskEditor.mirrorVertical) are present in the translation files.Note: A past review comment suggested adding keyboard shortcuts. Per the PR description, keyboard shortcuts for these transform actions were added in
src/extensions/core/maskEditor.ts, so that concern has been addressed.
|
Thank you for catching some of the improvements and the unnecessary ternary, @DrJKL. Made the changes you mentioned but unfortunately don't think we can consolidate the mask, rgb, and img ImageData | ImageBitmap. |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/maskeditor/dialog/TopBarHeader.vue (1)
12-36: Inconsistent icon fill classes between undo and redo buttons.The undo button (line 14) uses
fill-currentwhile the redo button (line 29) usesfill-[var(--input-text)]. This inconsistency could cause visual differences between the two icons. Consider using the same fill class for both.🔧 Suggested fix
<svg viewBox="0 0 15 15" - class="h-6.25 w-6.25 pointer-events-none fill-current" + class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]" >Or alternatively, update the redo icon to use
fill-currentfor consistency.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.tssrc/extensions/core/maskeditor.tssrc/locales/en/main.json
🧰 Additional context used
📓 Path-based instructions (14)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
src/**/*.vue: Use Vue 3 Single File Components (SFCs) with Composition API only
Use<script setup lang="ts">for component logic in Vue SFCs
Avoid<style>blocks in Vue components - use Tailwind 4 styling instead
Use vue-i18n for all string literals in Vue components - place translation entries insrc/locales/en/main.json
Use Tailwind utility classes instead ofdark:variant - use semantic values fromstyle.csstheme (e.g.,bg-node-component-surface)
Usecn()utility from@/utils/tailwindUtilfor merging Tailwind class names instead of:class="[]"or hardcoding
Never use!importantor!Tailwind prefix - fix interfering classes instead
Use Tailwind fraction utilities instead of arbitrary percentage values (e.g.,w-4/5instead ofw-[80%])
Use TypeScript Vue 3.5 style default prop declaration with reactive props destructuring - avoidwithDefaultsor runtime props
PreferdefineModelover separately defining a prop and emit for v-model bindings
Define slots via template usage, not viadefineSlots
Use same-name shorthand for slot prop bindings (e.g.,:isExpandedinstead of:is-expanded="isExpanded")
Do not import Vue macros unnecessarily
Avoid new usage of PrimeVue components
Use Tailwind's plurals system via i18n instead of hardcoding ...
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsName Vue components in PascalCase (e.g.,
MenuHamburger.vue)
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/maskeditor/dialog/TopBarHeader.vue
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
🧠 Learnings (30)
📚 Learning: 2025-12-11T03:55:57.926Z
Learnt from: simula-r
Repo: Comfy-Org/ComfyUI_frontend PR: 7252
File: src/renderer/extensions/vueNodes/components/ImagePreview.vue:151-158
Timestamp: 2025-12-11T03:55:57.926Z
Learning: In src/renderer/extensions/vueNodes/components/ImagePreview.vue and LGraphNode.vue, keyboard navigation for image galleries should respond to node-level focus (via keyEvent injection from LGraphNode), not require focus within the image preview wrapper itself. This allows users to navigate the gallery with arrow keys immediately when the node is focused/selected.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/extensions/core/maskeditor.ts
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,vue} : Leverage VueUse functions for performance-enhancing composables
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize Vue 3's Teleport component when needed
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-22T21:36:08.369Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/platform/cloud/subscription/components/PricingTable.vue:185-201
Timestamp: 2025-12-22T21:36:08.369Z
Learning: In Vue components, avoid creating single-use variants for common UI components (e.g., Button and other shared components). Aim for reusable variants that cover multiple use cases. It’s acceptable to temporarily mix variant props with inline Tailwind classes when a styling need is unique to one place, but plan and consolidate into shared, reusable variants as patterns emerge across the codebase.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,vue} : Use VueUse function for useI18n in composition API for string literals
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-09T21:40:12.361Z
Learnt from: benceruleanlu
Repo: Comfy-Org/ComfyUI_frontend PR: 7297
File: src/components/actionbar/ComfyActionbar.vue:33-43
Timestamp: 2025-12-09T21:40:12.361Z
Learning: In Vue single-file components, allow inline Tailwind CSS class strings for static classes and avoid extracting them into computed properties solely for readability. Prefer keeping static class names inline for simplicity and performance. For dynamic or conditional classes, use Vue bindings (e.g., :class) to compose classes.
Applies to all Vue files in the repository (e.g., src/**/*.vue) where Tailwind utilities are used for static styling.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-16T22:26:49.463Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.vue:17-17
Timestamp: 2025-12-16T22:26:49.463Z
Learning: In Vue 3.5+ with <script setup>, when using defineProps<Props>() with partial destructuring (e.g., const { as = 'button', class: customClass = '' } = defineProps<Props>() ), props that are not destructured (e.g., variant, size) stay accessible by name in the template scope. This pattern is valid: you can destructure only a subset of props for convenience while referencing the remaining props directly in template expressions. Apply this guideline to Vue components across the codebase (all .vue files).
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2026-01-08T02:26:18.357Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7893
File: src/components/button/IconGroup.vue:5-6
Timestamp: 2026-01-08T02:26:18.357Z
Learning: In components that use the cn utility from '@/utils/tailwindUtil' with tailwind-merge, rely on the behavior that conflicting Tailwind classes are resolved by keeping the last one. For example, cn('base-classes bg-default', propClass) will have any conflicting background class from propClass override bg-default. This additive pattern is intentional and aligns with the shadcn-ui convention; ensure you document or review expectations accordingly in Vue components.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vuesrc/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-18T02:07:38.870Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7598
File: src/components/sidebar/tabs/AssetsSidebarTab.vue:131-131
Timestamp: 2025-12-18T02:07:38.870Z
Learning: Tailwind CSS v4 safe utilities (e.g., items-center-safe, justify-*-safe, place-*-safe) are allowed in Vue components under src/ and in story files. Do not flag these specific safe variants as invalid when reviewing code in src/**/*.vue or related stories.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T21:15:46.862Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:46.862Z
Learning: In the ComfyUI_frontend repository, for Vue components, do not add aria-label to buttons that have visible text content (e.g., buttons containing <span> text). The visible text provides the accessible name. Use aria-label only for elements without visible labels (e.g., icon-only buttons). If a button has no visible label, provide a clear aria-label or associate with an aria-labelledby describing its action.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-21T01:06:02.786Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7649
File: src/components/graph/selectionToolbox/ColorPickerButton.vue:15-18
Timestamp: 2025-12-21T01:06:02.786Z
Learning: In Comfy-Org/ComfyUI_frontend, in Vue component files, when a filled icon is required (e.g., 'pi pi-circle-fill'), you may mix PrimeIcons with Lucide icons since Lucide lacks filled variants. This mixed usage is acceptable when one icon library does not provide an equivalent filled icon. Apply consistently across Vue components in the src directory where icons are used, and document the rationale when a mixed approach is chosen.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2025-12-18T16:03:02.066Z
Learnt from: henrikvilhelmberglund
Repo: Comfy-Org/ComfyUI_frontend PR: 7617
File: src/components/actionbar/ComfyActionbar.vue:301-308
Timestamp: 2025-12-18T16:03:02.066Z
Learning: In the ComfyUI frontend queue system, useQueuePendingTaskCountStore().count indicates the number of tasks in the queue, where count = 1 means a single active/running task and count > 1 means there are pending tasks in addition to the active task. Therefore, in src/components/actionbar/ComfyActionbar.vue, enable the 'Clear Pending Tasks' button only when count > 1 to avoid clearing the currently running task. The active task should be canceled using the 'Cancel current run' button instead. This rule should be enforced via a conditional check on the queue count, with appropriate disabled/aria-disabled states for accessibility, and tests should verify behavior for count = 1 and count > 1.
Applied to files:
src/components/maskeditor/dialog/TopBarHeader.vue
📚 Learning: 2026-01-06T19:17:12.355Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7746
File: src/platform/assets/composables/useUploadModelWizard.ts:207-219
Timestamp: 2026-01-06T19:17:12.355Z
Learning: In `src/platform/assets/composables/useUploadModelWizard.ts`, the `uploadModel()` function should have a concurrency guard at the beginning that checks if `isUploading.value` is already true and returns false early to prevent race conditions from multiple rapid invocations.
Applied to files:
src/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/maskeditor/useCanvasHistory.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/composables/maskeditor/useCanvasHistory.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasHistory.tssrc/extensions/core/maskeditor.tssrc/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-09T04:35:43.971Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:43.971Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.
Applied to files:
src/locales/en/main.json
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/extensions/core/maskeditor.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Take advantage of `TypedArray` `subarray` when appropriate
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Do not add or retain redundant comments - clean as you go
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
📚 Learning: 2025-12-05T06:11:09.383Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7177
File: src/platform/assets/components/UploadModelFooter.vue:72-78
Timestamp: 2025-12-05T06:11:09.383Z
Learning: For the ComfyUI_frontend repository, avoid suggesting comments that would be redundant when the code is already self-explanatory through descriptive naming (e.g., filenames, prop names, aria-labels). The project prefers clean code without unnecessary documentation comments.
Applied to files:
src/composables/maskeditor/useCanvasTransform.ts
🧬 Code graph analysis (1)
src/extensions/core/maskeditor.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (16)
src/locales/en/main.json (1)
977-980: LGTM!The new localization keys follow the existing naming conventions and are appropriately placed within the
maskEditorsection. Based on learnings, other locale files are auto-generated on release, so only these English entries are required.src/composables/maskeditor/useCanvasHistory.ts (5)
4-9: LGTM!The
CanvasStateinterface provides clear typing for the three-layer state structure. Using a union typeImageData | ImageBitmapcorrectly accommodates both state capture methods.
29-75: LGTM!The
saveInitialStatefunction properly validates all three canvases and their contexts before capturing state. TherequestAnimationFrameretry pattern handles async canvas initialization gracefully.
77-132: LGTM!The
saveStatefunction correctly handles both provided data (from transformations) and captured data paths. The all-or-nothing check on line 106 ensures consistency when external data is passed. Memory cleanup viacleanupStateon pruned states prevents memory leaks.
146-186: LGTM!The
restoreStatefunction properly handles dimension changes during rotation undo/redo by resizing all canvases before rendering. The dual handling ofImageBitmap(viadrawImage) andImageData(viaputImageData) is correct, and the loop pattern reduces code duplication.
188-199: LGTM!Proper memory management with
ImageBitmap.close()for all three layers. This prevents GPU memory leaks during extended editing sessions.src/components/maskeditor/dialog/TopBarHeader.vue (2)
40-103: LGTM!The new rotate and mirror buttons are well-implemented with proper i18n tooltips and consistent styling. The SVG icons are appropriately sized and use pointer-events-none to prevent interaction issues.
163-193: LGTM!The async transform handlers properly use try/catch for error handling. While errors are only logged to console, the underlying transform functions provide detailed error information. Consider adding user-facing error notifications in a future iteration for better UX.
src/extensions/core/maskeditor.ts (1)
114-149: LGTM!The new extension commands follow the established pattern and properly guard against execution when the mask editor is closed. The async/await usage is correct, and error handling is delegated to the underlying transform functions.
src/composables/maskeditor/useCanvasTransform.ts (7)
61-103: LGTM!The mirror logic correctly handles both horizontal (X-axis flip) and vertical (Y-axis flip) operations. Since dimensions don't change, the stride calculation remains the original width.
108-115: LGTM!The premultiplication logic is correct for WebGPU texture uploads. Using
Math.round()prevents floating-point artifacts in the color values.
184-228: LGTM!The
rotateClockwisemethod correctly orchestrates the full transformation workflow: validation, rotation of all three layers, dimension swap, GPU texture recreation (when active), and history recording.
233-351: LGTM!The remaining transform methods (
rotateCounterclockwise,mirrorHorizontal,mirrorVertical) follow a consistent pattern and correctly handle their respective transformations. Mirror operations appropriately preserve canvas dimensions while rotation operations swap width and height.
353-358: LGTM!The composable exposes a clean, focused API with only the four transform operations. This follows the guideline to minimize the surface area of composables.
121-179: TheimgCanvaslayer is intentionally excluded from GPU texture recreation because it does not participate in GPU rendering. The brush drawing system only maintains GPU textures for the mask and RGB layers (seeuseBrushDrawing.tslines 63-64, 502-525). TheimgCanvasserves solely as the base image for CPU-side composition inuseMaskEditorSaverwhen exporting the final result; it is never accessed during GPU brush rendering operations.
12-56: Rotation coordinate calculation is correct.The destination index calculation on line 45 properly handles the coordinate transformation for 90° rotations. After rotation, the new stride correctly uses the original height value, and this works correctly for non-square images since the dimensions are properly swapped (lines 209-214, 258-263). Both clockwise and counter-clockwise transformations are mathematically sound, and the accompanying mirror operations are also correctly implemented.
|
Looks like the unit tests need to be updated, otherwise should be good. |
|
@DrJKL Updated |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
5-23: Replaceanymocks with typed mocks and usevi.hoisted()for the store mock.The current mocks use
anytype (mockImgCanvas,mockImgCtx, plusnull as any), which violates the repo rule "Never useanytype." Additionally, the shared mutablemockStoreshould usevi.hoisted()to keep module mocks contained and prevent global mutable state, following the established pattern throughout the codebase.Proposed refactor
import { beforeEach, describe, expect, it, vi } from 'vitest' import { nextTick } from 'vue' import { useCanvasHistory } from '@/composables/maskeditor/useCanvasHistory' -let mockMaskCanvas: any -let mockRgbCanvas: any -let mockImgCanvas: any -let mockMaskCtx: any -let mockRgbCtx: any -let mockImgCtx: any +type MockCanvas = Pick<HTMLCanvasElement, 'width' | 'height'> +type MockCtx = Pick< + CanvasRenderingContext2D, + 'getImageData' | 'putImageData' | 'clearRect' | 'drawImage' +> + +let mockMaskCanvas: MockCanvas +let mockRgbCanvas: MockCanvas +let mockImgCanvas: MockCanvas +let mockMaskCtx: MockCtx +let mockRgbCtx: MockCtx +let mockImgCtx: MockCtx -const mockStore = { - maskCanvas: null as any, - rgbCanvas: null as any, - imgCanvas: null as any, - maskCtx: null as any, - rgbCtx: null as any, - imgCtx: null as any -} +const { mockStore } = vi.hoisted(() => ({ + mockStore: { + maskCanvas: null as MockCanvas | null, + rgbCanvas: null as MockCanvas | null, + imgCanvas: null as MockCanvas | null, + maskCtx: null as MockCtx | null, + rgbCtx: null as MockCtx | null, + imgCtx: null as MockCtx | null + } +})) vi.mock('@/stores/maskEditorStore', () => ({ useMaskEditorStore: vi.fn(() => mockStore) }))
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasHistory.test.ts:
- Around line 246-256: The test for no-op undo in useCanvasHistory only checks
mockMaskCtx.putImageData call count; instead clear relevant spies before
invoking the action and assert none of the canvas layer spies were called: call
mockMaskCtx.putImageData.mockClear(), mockRgbCtx.putImageData.mockClear(), and
mockImgCtx.drawImage.mockClear() (or their equivalents) before history.undo(),
then assert each spy not.toHaveBeenCalled(); apply the same change pattern to
the other no-op undo/redo tests referenced (the tests around lines 282-289,
313-323, 347-361) so all mask/rgb/img layers are verified untouched.
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Around line 145-151: The test for useCanvasTransform currently only checks
that mockCanvasHistory.saveState was called; update it to assert the saved
argument matches the actual transformed state by capturing the expected state
after rotateClockwise and verifying mockCanvasHistory.saveState was calledWith
that state (or use toMatchObject/toEqual against a snapshot). Locate
useCanvasTransform and the rotateClockwise invocation in the test, call or read
the transform's state/getState after rotation to build the expected object, and
replace the loose expect(mockCanvasHistory.saveState).toHaveBeenCalled() with an
assertion that the first argument equals the expected transformed state.
- Around line 31-33: Replace the top-level vi.mock call with a hoisted mock so
module mock state is explicit: wrap the existing
vi.mock('@/stores/maskEditorStore', () => ({ useMaskEditorStore: vi.fn(() =>
mockStore) })) inside vi.hoisted(() => { ... }); ensure any mutable mockStore is
declared/initialized in a scope compatible with the hoisted wrapper so the
useMaskEditorStore mock returns the intended mockStore instance.
- Around line 334-380: The mirrorVertical tests are missing the GPU texture
recreation assertions present in mirrorHorizontal; update the mirrorVertical
spec for useCanvasTransform.mirrorVertical to also verify GPU-related calls by
adding the same assertions used in the mirrorHorizontal test (e.g., assert the
mocked GPU/renderer texture recreation or upload methods were called after
mirrorVertical runs), referencing the same mocks used in the file
(mirrorVertical, mockMaskCanvas/mockRgbCanvas/mockImgCanvas,
mockMaskCtx/mockRgbCtx/mockImgCtx, mockCanvasHistory) so GPU texture recreation
is covered similarly to the horizontal case.
- Around line 507-547: Add stricter assertions for pendingGPUMaskData and
pendingGPURgbData after calling rotateClockwise/mirrorHorizontal: assert each is
an instance of Uint8ClampedArray, its .buffer is an ArrayBuffer (not a
SharedArrayBuffer), its .length equals expectedWidth * expectedHeight * 4 (use
mockMaskCanvas.width/height or swapped dims for rotation), and verify
premultiplied-alpha semantics by checking for all pixel indices that R <= A, G
<= A, and B <= A (sample a few indices or loop all pixels) to ensure color
channels are premultiplied by alpha.
- Around line 4-29: Replace all uses of the loose any mocks with explicit mock
types: define lightweight interfaces for the canvas and context objects (e.g.,
IMockCanvas, IMockContext) or reuse existing DOM/Canvas types, then type
mockMaskCanvas, mockRgbCanvas, mockImgCanvas, mockMaskCtx, mockRgbCtx,
mockImgCtx accordingly; for mockStore, use the Partial<StoreState> as StoreState
(or Partial<YourStoreType> as YourStoreType) pattern and assign
mockCanvasHistory to its typed canvasHistory property so tests keep strong
typing while still allowing partial mocks.
- Around line 237-272: The test only checks dimensions after
rotateCounterclockwise() but never verifies pixel differences vs
rotateClockwise(); update the test in useCanvasTransform.test.ts to (1) reuse
the asymmetric pattern creator (createAsymmetricImageData) and
mockMaskCtx.getImageData for a fresh copy before each rotation, (2) call
transform.rotateCounterclockwise() and capture the first
mockMaskCtx.putImageData call, then reset mocks, call
transform.rotateClockwise() and capture its putImageData result, and (3) assert
that the two resulting ImageData objects from mockMaskCtx.putImageData have
different pixel buffers (compare their .data contents) and that widths/heights
are swapped appropriately for each rotation to ensure direction matters. Use the
functions/mocks rotateCounterclockwise, rotateClockwise,
createAsymmetricImageData, mockMaskCtx.getImageData, and
mockMaskCtx.putImageData to locate where to change the test.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
🧠 Learnings (14)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.tssrc/composables/maskeditor/useCanvasHistory.test.ts
🧬 Code graph analysis (2)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
src/composables/maskeditor/useCanvasHistory.ts (1)
useCanvasHistory(11-211)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: lint-and-format
- GitHub Check: collect
🔇 Additional comments (3)
src/composables/maskeditor/useCanvasTransform.test.ts (2)
275-332: LGTM!The
mirrorHorizontaltests provide good behavioral coverage: dimension preservation, canvas API calls, history persistence, and GPU integration.
382-477: Good pixel-level verification.These tests validate actual transformation correctness at the pixel level, which is valuable for catching bugs in the rotation/mirror algorithms. Consider adding similar tests for
rotateCounterclockwiseandmirrorVerticalto complete coverage.src/composables/maskeditor/useCanvasHistory.test.ts (1)
73-101: Good: tests now consistently assert 3-layer behavior (mask/rgb/img).The added
imgmocks and assertions align with the new 3-layer history behavior (initial save, saveState, undo/redo, clearStates, and missing-context early returns).Also applies to: 111-121, 150-165, 202-210, 230-244, 292-311, 378-393, 477-495
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasHistory.test.ts:
- Around line 5-19: Replace the broad `any` types on mockMaskCanvas,
mockRgbCanvas, mockImgCanvas and mockMaskCtx, mockRgbCtx, mockImgCtx with proper
DOM/Canvas types (e.g., HTMLCanvasElement | null for canvas variables and
CanvasRenderingContext2D | null for context variables) and type `mockStore` as a
partial of the real store shape (e.g., use `Partial<YourStoreInterface>` or
`Partial<typeof realStore>` then cast to the expected type using the `as
Partial<...> as ...` pattern) so tests use strict TypeScript types instead of
`any`; update references in this test file (useCanvasHistory.test.ts) to match
those typed symbols.
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Line 27: The tgpuRoot test variable is typed as any which violates guidelines;
change its type to unknown (e.g., replace the declaration of tgpuRoot from any
to unknown) since the tests only check its truthiness and the concrete shape
isn’t used, ensuring stricter type safety without affecting the mock usage.
- Around line 65-100: The test global mocks for ImageData and ImageBitmap use
forbidden `as any` casts; instead remove `as any` and either cast via `as
unknown as typeof globalThis.ImageData` / `as unknown as typeof
globalThis.ImageBitmap` or add a module/global declaration to augment the global
types and assign the classes directly to `globalThis.ImageData` and
`globalThis.ImageBitmap`; update the assignments for the ImageData and
ImageBitmap mocks (the mock classes and their constructors) to use one of those
safe casts or proper global augmentation so the mocks satisfy TypeScript without
`as any`.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧠 Learnings (24)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Be parsimonious in testing - do not write redundant tests
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Do not write change detector tests - avoid tests that only assert default values
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `as any` type assertions - fix the underlying type issue
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `any` type - use proper TypeScript types
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧬 Code graph analysis (2)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
src/composables/maskeditor/useCanvasHistory.ts (1)
useCanvasHistory(11-211)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: playwright-tests-chromium-sharded (7, 8)
- GitHub Check: playwright-tests-chromium-sharded (8, 8)
- GitHub Check: playwright-tests-chromium-sharded (1, 8)
- GitHub Check: playwright-tests-chromium-sharded (3, 8)
- GitHub Check: playwright-tests-chromium-sharded (5, 8)
- GitHub Check: playwright-tests-chromium-sharded (6, 8)
- GitHub Check: playwright-tests-chromium-sharded (2, 8)
- GitHub Check: playwright-tests-chromium-sharded (4, 8)
- GitHub Check: playwright-tests (chromium-2x)
- GitHub Check: playwright-tests (chromium-0.5x)
- GitHub Check: playwright-tests (mobile-chrome)
🔇 Additional comments (3)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
179-716: Excellent test coverage and structure!The test suite provides comprehensive behavioral coverage:
- Rotation tests validate dimension swapping, correct data handling, history persistence, and distinct results for clockwise vs counterclockwise rotations
- Mirroring tests verify dimension preservation and correct transformations
- Pixel-level tests (lines 501-596) are particularly valuable—they validate actual pixel manipulations using 2x2 test patterns with distinct colors, ensuring transformations are correct at the data level
- Error handling tests verify graceful handling of missing canvases/contexts
- GPU integration tests (lines 626-716) thoroughly validate texture recreation flags, dimension handling, ArrayBuffer backing, premultiplied alpha constraints, and inactive GPU behavior
The asymmetric pattern test (lines 323-380) is a clever approach to verify that clockwise and counterclockwise rotations produce different results, catching potential bugs where both operations might use the same logic.
Tests follow best practices: they validate actual behavior rather than just mocking, cover both happy paths and edge cases, and ensure proper integration with the GPU subsystem.
Based on learnings: Write tests for all changes, especially bug fixes to catch future regressions.
src/composables/maskeditor/useCanvasHistory.test.ts (2)
73-100: Excellent three-layer test coverage.The img layer integration is consistently applied across all test scenarios:
- Initialization checks all three contexts (Line 118)
- State saving validates all three layers (Lines 157-163, 209-210)
- Undo/redo operations verify all three contexts (Lines 241, 253-254, 259, 310, 316)
- Cleanup paths include the img layer (Lines 402-403, 408, 503)
The mock setup for imgCtx and imgCanvas mirrors the existing mask/rgb structure, ensuring uniform test behavior across all layers.
Also applies to: 118-118, 157-163, 209-210, 220-221, 241-241, 253-254, 259-259, 310-310, 316-316, 402-403, 408-408, 503-503
246-260: Improved boundary condition tests.The updated boundary tests properly verify that undo/redo operations:
- Clear previous mock calls before testing boundaries
- Verify that
putImageDatais not called when no states are available- Test all three contexts consistently
This aligns with the PR objective to remove alert-based feedback and rely on early returns, ensuring global undo/redo shortcuts are properly restricted when the Mask Editor is at history boundaries.
Also applies to: 280-297, 321-335, 359-377
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasHistory.test.ts:
- Around line 5-30: Replace the module-level mutable mock variables
(mockMaskCanvas, mockRgbCanvas, mockImgCanvas, mockMaskCtx, mockRgbCtx,
mockImgCtx and the mockStore object) with a hoisted container created via
vi.hoisted() (e.g., const mockRefs = vi.hoisted(() => ({ maskCanvas: null,
rgbCanvas: null, imgCanvas: null, maskCtx: null, rgbCtx: null, imgCtx: null
}))). Update tests to read/write mockRefs.maskCtx, mockRefs.maskCanvas, etc.,
instead of the top-level variables so each test run gets isolated mock state and
avoids cross-test pollution while preserving the same MaskEditorStoreState
shape.
- Around line 70-106: Replace the use of "as unknown as" with the explicit
partial-cast pattern for the mock objects; update mockMaskCtx, mockRgbCtx,
mockImgCtx to use "as Partial<CanvasRenderingContext2D> as
CanvasRenderingContext2D" and update mockMaskCanvas, mockRgbCanvas,
mockImgCanvas to use "as Partial<HTMLCanvasElement> as HTMLCanvasElement" so the
tests clearly express these are partial implementations while satisfying the
strict types.
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Around line 283-322: The test only asserts that clockwise vs counterclockwise
rotations differ but doesn't verify correctness; update or add explicit
pixel-based assertions for useCanvasTransform's rotateCounterclockwise and
rotateClockwise by using a small deterministic pattern (e.g., 2x2) returned from
mockMaskCtx.getImageData, then call transform.rotateCounterclockwise() (and
separately rotateClockwise()) and assert exact RGBA values at specific indices
in the ImageData passed to mockMaskCtx.putImageData (reference the functions
useCanvasTransform, rotateCounterclockwise, rotateClockwise and the mocks
mockMaskCtx/mockMaskCanvas) to ensure the rotations map source pixels to the
expected destination indices.
- Around line 346-354: Add three tests to the mirrorVertical suite: (1) a GPU
texture recreation test that sets mockStore.tgpuRoot (or equivalent) before
calling useCanvasTransform().mirrorVertical() and then asserts
mockStore.gpuTexturesNeedRecreation is true and mockStore.gpuTextureWidth/Height
match the new canvas dimensions; (2) a pixel-level verification that sets
mockMaskCanvas.width/height to 2, stubs mockMaskCtx.getImageData to return a
known 2x2 ImageData pattern, calls mirrorVertical(), and inspects the first
argument passed to mockMaskCtx.putImageData to assert pixels were flipped
vertically (check appropriate indices in result.data); and (3) an error-handling
test mirroring the pattern used in rotateClockwise tests to ensure
mirrorVertical throws or handles invalid state (use the same setup used in
rotateClockwise error test and assert the expected error/logging behavior).
Ensure all tests call useCanvasTransform() and reference mirrorVertical() so
they target the correct function.
- Around line 71-86: The test polyfill constructor for the ImageData replacement
uses non-null assertions on width and height (dataOrWidth, width, height) which
bypass type safety; replace those `!` assertions by adding an explicit runtime
guard or TypeScript overloads: check at the start of the constructor whether
dataOrWidth is a Uint8ClampedArray or a number, and if number-branch ensure
width and height are present (throw a clear error if missing) or define
constructor overloads so width/height are required in that signature; update
uses in the Uint8ClampedArray branch to read width/height only after the guard
so no `!` is needed, keeping the exported object cast as the ImageData polyfill.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧠 Learnings (26)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to browser_tests/**/*.spec.ts : Follow Playwright best practices for E2E testing
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Do not write change detector tests - avoid tests that only assert default values
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Be parsimonious in testing - do not write redundant tests
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `as any` type assertions - fix the underlying type issue
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `any` type - use proper TypeScript types
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{ts,tsx} : Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧬 Code graph analysis (2)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
src/composables/maskeditor/useCanvasHistory.ts (1)
useCanvasHistory(11-211)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: test
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: collect
🔇 Additional comments (9)
src/composables/maskeditor/useCanvasHistory.test.ts (6)
36-47: LGTM!The ImageBitmap polyfill pattern is appropriate for test environments that lack native browser API support.
117-166: LGTM!The initialization tests properly verify all three contexts (mask, rgb, img) are captured, and correctly test the deferred initialization behavior when canvas or context is not ready.
168-246: LGTM!The saveState tests comprehensively cover the three-layer capture behavior, redo state clearing, maxStates limit enforcement, and guard conditions for missing contexts.
248-316: LGTM!The undo tests properly verify restoration across all three layers and correctly test the boundary conditions (no undo available, multiple undos, preventing undo beyond first state).
318-396: LGTM!The redo tests mirror the undo tests appropriately, verifying three-layer restoration and boundary behavior.
531-583: LGTM!The edge case tests provide good coverage for stress scenarios (rapid saves, maxStates boundary, undo/redo cycling) and graceful handling of invalid states (zero-sized canvas).
src/composables/maskeditor/useCanvasTransform.test.ts (3)
1-34: LGTM! Strong TypeScript foundation for test mocks.The interface definitions provide excellent type safety for the mock structures, and the use of
unknownfortgpuRoot(line 27) demonstrates proper type safety while still allowing truthiness checks.
36-62: LGTM! Proper use of vi.hoisted() for module mocking.The hoisted mock setup follows best practices for keeping module mocks contained and avoiding global mutable state.
110-176: LGTM! Comprehensive test setup.The
beforeEachproperly resets all mock state and initializes the three canvas layers with appropriate test data.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
623-636: Unnecessary guard formockRefs.maskCanvas.The
if (mockRefs.maskCanvas)guard at line 624 is unnecessary sincebeforeEachalways initializesmockRefs.maskCanvasbefore each test runs. The guard adds slight confusion about when this could be null.♻️ Suggested simplification
it('should handle zero-sized canvas', () => { - if (mockRefs.maskCanvas) { - mockRefs.maskCanvas = { - width: 0, - height: 0 - } as Partial<HTMLCanvasElement> as HTMLCanvasElement - } + mockRefs.maskCanvas = { + width: 0, + height: 0 + } as Partial<HTMLCanvasElement> as HTMLCanvasElement const history = useCanvasHistory() history.saveInitialState() expect(window.requestAnimationFrame).toHaveBeenCalled() })
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Around line 278-337: The test "should correctly rotate pixels clockwise at
pixel level" is duplicated elsewhere in the "pixel-level transformations"
describe block; remove the redundant copy so only one comprehensive pixel-level
rotation test remains. Locate the duplicate by the test title "should correctly
rotate pixels clockwise at pixel level" (and the other occurrence in the
"pixel-level transformations" block) and delete one of them (prefer keeping the
version with clearer color naming and more comprehensive assertions) to avoid
redundant coverage.
- Around line 608-622: Add an assertion to the GPU integration test to also
verify pendingGPURgbData is created with the expected size after rotation: in
the 'should set GPU recreation flags for rotation' test where you call
useCanvasTransform() and await rotateClockwise(), assert that
mockStore.pendingGPURgbData exists and its length equals
mockStore.gpuTextureWidth * mockStore.gpuTextureHeight * 4 (or specifically 50 *
100 * 4 given the mocked dimensions), similar to the existing check for
pendingGPUMaskData; update the expectations around mockStore.pendingGPURgbData
alongside pendingGPUMaskData to ensure both buffers are validated.
- Around line 459-478: Add a pixel-level test for mirrorHorizontal analogous to
the mirrorVertical tests: create a test that draws known pixel data on
mockMaskCanvas (e.g., distinct left/right pixel colors), call
useCanvasTransform().mirrorHorizontal(), then read back canvas pixel data and
assert pixels have been horizontally flipped (left pixels now on right and vice
versa). Also include a variant that sets mockStore.tgpuRoot to simulate GPU
active and assert gpuTexturesNeedRecreation and gpuTextureWidth/Height are set
correctly after the flip; reference useCanvasTransform, mirrorHorizontal,
mockMaskCanvas, and mockStore in the assertions.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
🧠 Learnings (28)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `as any` type assertions - fix the underlying type issue
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `any` type - use proper TypeScript types
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to browser_tests/**/*.spec.ts : Follow Playwright best practices for E2E testing
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.ts : Favor pure functions, especially testable ones
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasHistory.test.tssrc/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{ts,tsx} : Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Aim for behavioral coverage of critical and new features in unit tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Be parsimonious in testing - do not write redundant tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧬 Code graph analysis (2)
src/composables/maskeditor/useCanvasHistory.test.ts (1)
src/composables/maskeditor/useCanvasHistory.ts (1)
useCanvasHistory(11-211)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: test
- GitHub Check: lint-and-format
- GitHub Check: collect
- GitHub Check: setup
🔇 Additional comments (10)
src/composables/maskeditor/useCanvasTransform.test.ts (5)
1-35: LGTM!The mock interfaces are well-typed and provide a clear contract for the test mocks. Using local interfaces for partial mock types is appropriate here since these are test-specific shapes that don't need to match the full implementation types.
36-62: LGTM!Good use of
vi.hoisted()to create isolated mock state, preventing test pollution. The mock structure properly includes all GPU-related properties needed for testing the transform operations.
64-112: LGTM!The global mocks for
ImageDataandImageBitmapcorrectly handle the constructor overloads and use theas unknown as typeofpattern rather thanas any, aligning with the coding guidelines.
122-188: LGTM!The
beforeEachsetup properly initializes all three canvas layers with fresh mocks and resets the store state, ensuring test isolation.
340-457: LGTM!Good test coverage for counterclockwise rotation. The asymmetric data test at lines 417-456 is particularly valuable for verifying that clockwise and counterclockwise rotations produce distinct results.
src/composables/maskeditor/useCanvasHistory.test.ts (5)
5-62: LGTM!The
MaskEditorStoreStateinterface and the getter/setter proxy pattern formockStoreprovide clean, type-safe mock management. Usingvi.hoisted()ensures proper isolation per the coding guidelines.
94-139: LGTM!The
beforeEachsetup properly initializes all three canvas layers using the recommendedas Partial<T> as Tcasting pattern. TherequestAnimationFramemock includes a safeguard against infinite recursion.
149-164: LGTM!The initialization tests properly verify that
getImageDatais called on all three contexts (mask, rgb, img) when saving the initial state, reflecting the expanded three-layer model.
213-297: LGTM!The
saveStatetests properly cover the three-layer model with assertions on all contexts. The use ofvi.mocked()formockClear()maintains type safety.
299-447: LGTM!The undo/redo tests thoroughly verify that
putImageDatais called (or not called) on all three contexts in appropriate scenarios. The state transition tests are comprehensive.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Around line 610-638: Remove the redundant "pixel-level transformations"
describe block (including its nested it test) that duplicates the existing
rotateClockwise pixel tests; delete the block referencing
mockMaskCanvas/mockMaskCtx and the call to
useCanvasTransform().rotateClockwise(), leaving the earlier comprehensive
rotateClockwise suite intact and ensuring no other tests rely on the removed
fixtures.
- Around line 4-34: Replace the local mock interfaces (IMockCanvas,
IMockContext, IMockCanvasHistory, IMockStore) with the real store/type
definitions from the implementation: import the MaskEditorStore (or equivalent)
type from '@/stores/maskEditorStore' and create your test mocks as partials cast
back to the full type (e.g., mockStore = { ... } as Partial<MaskEditorStore> as
MaskEditorStore), and similarly use real Canvas/Context types from the
implementation instead of IMockCanvas/IMockContext to avoid type drift while
keeping only the needed mocked fields.
- Around line 640-655: Tests don't cover the SharedArrayBuffer rejection and
premultiply-alpha behavior in the GPU path; add two unit tests that call
useCanvasTransform().rotateClockwise(): (1) simulate a SharedArrayBuffer-backed
ImageData by making mockMaskCtx.getImageData return { data: new
Uint8ClampedArray(new SharedArrayBuffer(...)), width, height } with
mockStore.tgpuRoot set and assert console.error was called with a message
containing "SharedArrayBuffer" to verify the detection branch; (2) simulate a
1x1 ImageData with a semi-transparent pixel (e.g., [200,100,50,128]), set
mockStore.tgpuRoot and canvas size, call rotateClockwise and assert
mockStore.pendingGPUMaskData contains premultiplied RGB values (200*128/255
≈100, 100*128/255 ≈50, 50*128/255 ≈25) and alpha preserved, thereby exercising
the premultiplyData code path used in useCanvasTransform.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧠 Learnings (27)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Aim for behavioral coverage of critical and new features in unit tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `as any` type assertions - fix the underlying type issue
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `any` type - use proper TypeScript types
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{ts,tsx} : Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to browser_tests/**/*.spec.ts : Follow Playwright best practices for E2E testing
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Be parsimonious in testing - do not write redundant tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧬 Code graph analysis (1)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: lint-and-format
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: collect
🔇 Additional comments (1)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
486-492: Minor formatting inconsistency.Multiple assignments per line here differ from the style used elsewhere in the file (e.g., lines 284-303). The CI formatter (
pnpm format) will normalize this, so no action required.
|
@DrJKL I think the tests are fine as they are now and they all seem to pass. Mind reviewing the real changes and approving if satisfactory? |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @src/composables/maskeditor/useCanvasTransform.test.ts:
- Around line 282-305: The createTestPattern helper is duplicated across
multiple tests in useCanvasTransform.test.ts; extract the function named
createTestPattern out of the individual tests and place a single shared helper
at the describe('useCanvasTransform') block scope so all tests (those currently
containing createTestPattern at lines around 282, 360, 483, 548) call the common
createTestPattern(), preserving the same Uint8ClampedArray pixel layout (TL red,
TR green, BL blue, BR yellow) and returned ImageData shape.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
src/composables/maskeditor/useCanvasTransform.test.ts
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Derive component types usingvue-component-type-helpers(ComponentProps,ComponentSlots) instead of separate type files
Use es-toolkit for utility functions
Minimize the surface area (exported values) of each module and composable
Favor pure functions, especially testable ones
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Use separateimport typestatements instead of inlinetypein mixed imports
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, 80-character width
Sort and group imports by plugin, runpnpm formatbefore committing
Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Write code that is expressive and self-documenting - avoid unnecessary comments
Do not add or retain redundant comments - clean as you go
Avoid mutable state - prefer immutability and assignment at point of declaration
Watch out for Code Smells and refactor to avoid them
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/composables/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts(e.g.,useForm.ts)
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src)/**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src)/**/*.test.ts: Unit and component tests belong intests-ui/orsrc/**/*.test.tsusing Vitest
Write tests for all changes, especially bug fixes to catch future regressions
Do not write tests dependent on non-behavioral features like utility classes or styles
Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Leverage Vitest's utilities for mocking where possible
Keep module mocks contained - do not use global mutable state within test files; usevi.hoisted()if necessary
Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,vue}: Usereffor reactive state,computed()for derived values, andwatch/watchEffectfor side effects in Composition API
Avoid usingrefwithwatchif acomputedwould suffice - minimize refs and derived state
Useprovide/injectfor dependency injection only when simpler alternatives (Store or shared composable) won't work
Leverage VueUse functions for performance-enhancing composables
Use VueUse function for useI18n in composition API for string literals
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx}: Keep functions short and functional
Minimize nesting (if statements, for loops, etc.)
Use function declarations instead of function expressions when possible
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts)
📄 CodeRabbit inference engine (AGENTS.md)
+(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts): Do not write change detector tests - avoid tests that only assert default values
Be parsimonious in testing - do not write redundant tests
Don't Mock What You Don't Own
Files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧠 Learnings (31)
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Keep module mocks contained - do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Leverage Vitest's utilities for mocking where possible
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Aim for behavioral coverage of critical and new features in unit tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-09T02:07:54.558Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7898
File: src/composables/usePaste.test.ts:248-248
Timestamp: 2026-01-09T02:07:54.558Z
Learning: In test files (e.g., any .test.ts or .test.tsx under src/...), when you create mock objects that partially implement an interface (such as LGraphNode), prefer casting with as Partial<InterfaceType> as InterfaceType rather than as any or as unknown as InterfaceType. This makes the incomplete implementation explicit while preserving type safety, improving readability and maintainability of tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Don't Mock What You Don't Own
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests that just test the mocks - ensure tests fail when code behaves unexpectedly
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `as any` type assertions - fix the underlying type issue
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-08T02:40:15.482Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7894
File: src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.test.ts:11-14
Timestamp: 2026-01-08T02:40:15.482Z
Learning: In TypeScript test files (e.g., any test under src), avoid duplicating interface/type definitions. Import real type definitions from the component modules under test and reference them directly, so there is a single source of truth and to prevent type drift. This improves maintainability and consistency across tests.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Never use `any` type - use proper TypeScript types
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Use Vue Test Utils for Component testing and follow best practices for making components easy to test
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{ts,tsx} : Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to browser_tests/**/*.spec.ts : Follow Playwright best practices for E2E testing
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Be parsimonious in testing - do not write redundant tests
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to src/**/*.ts : Favor pure functions, especially testable ones
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : When writing tests for subgraph-related code, always import from the barrel export at `@/lib/litegraph/src/litegraph` to avoid circular dependency issues
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src)/**/*.test.ts : Do not write tests dependent on non-behavioral features like utility classes or styles
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2026-01-10T00:24:17.662Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T00:24:17.662Z
Learning: Applies to +(tests-ui|src|browser_tests)/**/*.+(test.ts|spec.ts) : Do not write change detector tests - avoid tests that only assert default values
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-30T01:31:04.927Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7797
File: tests-ui/tests/lib/litegraph/src/widgets/ComboWidget.test.ts:648-648
Timestamp: 2025-12-30T01:31:04.927Z
Learning: In Vitest v4, when mocking functions that may be called as constructors (using new), the mock implementation must use function() or class syntax rather than an arrow function. Arrow mocks can cause '<anonymous> is not a constructor' errors. This is a breaking change from Vitest v3 where mocks could use an arrow function. Apply this guideline to test files that mock constructor-like calls (e.g., in tests under tests-ui, such as ComboWidget.test.ts) and ensure mock implementations are defined with function() { ... } or class { ... } to preserve constructor behavior.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
src/composables/maskeditor/useCanvasTransform.test.ts
🧬 Code graph analysis (1)
src/composables/maskeditor/useCanvasTransform.test.ts (1)
src/composables/maskeditor/useCanvasTransform.ts (1)
useCanvasTransform(6-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: collect
- GitHub Check: lint-and-format
- GitHub Check: setup
- GitHub Check: test
🔇 Additional comments (11)
src/composables/maskeditor/useCanvasTransform.test.ts (11)
1-3: LGTM: Clean importsThe import statements are properly structured and import only what's needed for the tests.
4-34: LGTM: Well-typed mock interfacesThe mock interfaces provide clear type definitions for the test doubles. Using
ReturnType<typeof vi.fn>for mock functions is idiomatic for Vitest.
36-62: LGTM: Proper use of vi.hoisted() for module mocksCorrectly uses
vi.hoisted()to create module-level mocks that are referenced in thevi.mock()call. This follows Vitest best practices and the coding guidelines for keeping module mocks contained.
64-99: LGTM: ImageData polyfill for test environmentThe ImageData polyfill correctly implements both constructor overloads and is necessary for the Node.js test environment. The type assertion
as unknown as typeof globalThis.ImageDatais an acceptable escape hatch for globalThis augmentation in tests.
101-112: LGTM: ImageBitmap polyfillMinimal but sufficient ImageBitmap polyfill for the test environment.
122-188: LGTM: Comprehensive test setupThe
beforeEachblock properly resets all mocks and creates fresh test fixtures for each test. ThecreateMockImageDatahelper returns completeImageDataobjects with all required properties.Note: The type assertion at line 137 (
as ImageData) is acceptable since the object implements all required properties. Alternatively, you could useas Partial<ImageData> as ImageDatato make the intent explicit, but the current approach is fine.
190-338: LGTM: Comprehensive rotateClockwise test coverageExcellent behavioral test suite covering:
- Dimension transformations (width/height swap)
- Canvas API interactions (getImageData, putImageData)
- History recording with correct dimensions
- Error handling when canvases unavailable
- GPU integration (both active and inactive paths)
- Pixel-level transformation correctness with distinct color patterns
The pixel-level test (lines 278-337) is particularly thorough, validating the exact transformation logic with a 2x2 grid of distinct colors. This ensures the rotation algorithm works correctly at the implementation level.
Based on learnings: "Aim for behavioral coverage of critical and new features in unit tests" ✅
340-457: LGTM: rotateCounterclockwise tests with differentiation validationGood test coverage for counterclockwise rotation. The test at lines 417-456 that validates CCW produces different results than CW using asymmetric image data is particularly valuable—it proves both rotations work correctly and distinctly.
459-522: LGTM: mirrorHorizontal test coverageGood test coverage validating that dimensions remain unchanged (unlike rotation), GPU integration works correctly, and pixel-level horizontal flipping is accurate.
524-620: LGTM: mirrorVertical test coverage including error handlingComprehensive test coverage including dimension validation, GPU integration, pixel-level transformation, and error handling when canvases aren't ready.
622-682: LGTM: Thorough GPU integration testingExcellent GPU integration tests that validate:
- Recreation flags and dimension updates
- Pending GPU data buffers created with correct size
- Premultiplication of alpha values with precise mathematical validation
The premultiply alpha test (lines 638-681) is particularly thorough—it uses specific RGBA values and validates the exact mathematical transformation (RGB × alpha/255), ensuring GPU texture data is prepared correctly for WebGPU's premultiplied alpha format.
|
Looks great, thanks! |
|
@brucew4yn3rp How do you feel about coderabbit so far? |
|
@DrJKL I think it's a useful tool to provide a first layer of review and help identify inefficiencies or potential nascent issues, but at the same time it almost tries too hard and implementing some of its suggestions would either not be practical or not work outright. |
|
@brucew4yn3rp If you have any specific awkward suggestions to call out, we can try to edit the AGENTS files to better guide it. |


Canvas Rotation and Mirroring
Overview
Adds rotation (90° left/right) and mirroring (horizontal/vertical) capabilities to the mask editor canvas. All three layers (image, mask, RGB) transform together. Redo and Undo respect transformations as new states. Keyboard shortcuts also added for all four functions in Keybinding settings.
Additionally, fixed the issue of ctrl+z and ctrl+y keyboard commands not restricting to the mask editor canvas while opened.
MaskEditor.Rotate.and.Mirror.mp4
What Changed
New Files
src/composables/maskeditor/useCanvasTransform.tsModified Files
src/composables/useCoreCommands.tssrc/stores/maskEditorStore.tssrc/composables/maskeditor/useBrushDrawing.tsgpuTexturesNeedRecreationsignalsrc/components/maskeditor/TopBarHeader.vuesrc/extensions/core/maskEditor.tsTranslation Files (e.g.,
src/locales/en.json)┆Issue is synchronized with this Notion page by Unito