Files
ComfyUI_frontend/src/core/graph/subgraph/resolveSubgraphInputLink.ts
Alexander Brown fe489ec87c [backport core/1.42] test: subgraph integration contracts and expanded Playwright coverage (#10327)
Backport of #10123, #9967, and #9972 to `core/1.42`

Includes three cherry-picks in dependency order:
1. #9972 — `fix: resolve all lint warnings` (clean)
2. #9967 — `test: harden subgraph test coverage and remove low-value
tests` (clean)
3. #10123 — `test: subgraph integration contracts and expanded
Playwright coverage` (1 conflict, auto-resolved by rerere from #10326)

See #10326 for core/1.41 backport with detailed conflict resolution
notes.

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
2026-03-19 18:24:31 -07:00

56 lines
1.7 KiB
TypeScript

import type { INodeInputSlot } from '@/lib/litegraph/src/interfaces'
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
type SubgraphInputLinkContext = {
inputNode: LGraphNode
targetInput: INodeInputSlot
getTargetWidget: () => ReturnType<LGraphNode['getWidgetFromSlot']>
}
export function resolveSubgraphInputLink<TResult>(
node: LGraphNode,
inputName: string,
resolve: (context: SubgraphInputLinkContext) => TResult | undefined
): TResult | undefined {
if (!node.isSubgraphNode()) return undefined
const inputSlot = node.subgraph.inputNode.slots.find(
(slot) => slot.name === inputName
)
if (!inputSlot) return undefined
// Iterate forward so the first connected source is the promoted representative,
// matching SubgraphNode._resolveLinkedPromotionBySubgraphInput.
for (const linkId of inputSlot.linkIds) {
const link = node.subgraph.getLink(linkId)
if (!link) continue
const { inputNode } = link.resolve(node.subgraph)
if (!inputNode) continue
if (!Array.isArray(inputNode.inputs)) continue
const targetInput = inputNode.inputs.find((entry) => entry.link === linkId)
if (!targetInput) continue
let cachedTargetWidget:
| ReturnType<LGraphNode['getWidgetFromSlot']>
| undefined
let hasCachedTargetWidget = false
const resolved = resolve({
inputNode,
targetInput,
getTargetWidget: () => {
if (!hasCachedTargetWidget) {
cachedTargetWidget = inputNode.getWidgetFromSlot(targetInput)
hasCachedTargetWidget = true
}
return cachedTargetWidget
}
})
if (resolved !== undefined) return resolved
}
return undefined
}