Skip to content

Vue node renderer ignores CORE_JOIN_ORDER: badges render as 'BETA #1' where the canvas renders '#1 BETA' #15662

Description

@christian-byrne

Summary

In Vue-nodes mode, a node's core badges render in a different order than on the classic canvas. Vue
shows BETA #1 my_pack; the canvas shows #1 BETA my_pack.

This is pre-existing on main and is already pinned by three it.fails in
src/composables/node/badgeRendererParity.test.ts. Filing it so the marker has an issue behind it.

Reproduction

Flip the three it.fails to it in src/composables/node/badgeRendererParity.test.ts and run it:

AssertionError: expected 'BETA #1 my_pack' to be '#1 BETA my_pack'
  Expected: "#1 BETA my_pack"
  Received: "BETA #1 my_pack"

Three cases: custom node under ShowAll, custom node under HideBuiltIn, core node under ShowAll.

Root cause

computeBadges emits core rows in array order — lifecycle, id, source:

// src/systems/badgeSystem.ts:69-71
const coreParts: [CoreBadgePart, NodeBadgeMode, string][] = [
  ['lifecycle', badgeModes.lifecycle, nodeDef?.lifecycleText ?? ''],
  ['id', badgeModes.id, `#${nodeId}`],
  ['source', badgeModes.source, nodeDef?.sourceText ?? '']
]

The classic canvas re-sorts them before drawing:

// src/types/badgeData.ts:2
export const CORE_JOIN_ORDER = ['id', 'lifecycle', 'source'] as const

// src/lib/litegraph/src/nodeBadgeDraw.ts:24-32  (joinedCoreText)
CORE_JOIN_ORDER.map((part) => byPart.get(part) ?? '').filter(...).join(' ')

usePartitionedBadges iterates nodeBadges(node) in emission order and pushes straight into
core[], never applying CORE_JOIN_ORDER:

// src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts:43-53
for (const row of node ? nodeBadges(node) : []) {
  ...
  core.push({ text: ... })
}

So CORE_JOIN_ORDER is documented as "Legacy canvas joins the core parts into a single badge in this
order"
and is honoured by exactly one of the two renderers.

Suggested fix

Sort core by CORE_JOIN_ORDER in usePartitionedBadges, so the ordering contract lives with the
data rather than in each renderer. That would flip the three it.fails to passing tests.

Scope

Comfy.VueNodes.Enabled is defaultValue: false but
defaultsByInstallVersion: { '1.41.0': isCloud || isDesktop }
(src/platform/settings/constants/coreSettings.ts:1197-1207), so OSS browser users see the correct
order and Cloud/Desktop users see BETA #1 today. Cosmetic only.

Context

Found while root-causing the badge-parity failure on #14246. Not introduced by that PR — the branch
actually fixes one adjacent case (hides built-in Vue badges is it.fails on main and passes on
the branch, i.e. #15567).

Related: #15567, #15619, #15568.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions