mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-11 00:10:40 +00:00
fix: stabilize nested subgraph promoted widget resolution (#9282)
## Summary Fix multiple issues with promoted widget resolution in nested subgraphs, ensuring correct value propagation, slot matching, and rendering for deeply nested promoted widgets. ## Changes - **What**: Stabilize nested subgraph promoted widget resolution chain - Use deep source keys for promoted widget values in Vue rendering mode - Resolve effective widget options from the source widget instead of the promoted view - Stabilize slot resolution for nested promoted widgets - Preserve combo value rendering for promoted subgraph widgets - Prevent subgraph definition deletion while other nodes still reference the same type - Clean up unused exported resolution types ## Review Focus - `resolveConcretePromotedWidget.ts` — new recursive resolution logic for deeply nested promoted widgets - `useGraphNodeManager.ts` — option extraction now uses `effectiveWidget` for promoted widgets - `SubgraphNode.ts` — unpack no longer force-deletes definitions referenced by other nodes ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9282-fix-stabilize-nested-subgraph-promoted-widget-resolution-3146d73d365081208a4fe931bb7569cf) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
55
src/core/graph/subgraph/resolveSubgraphInputLink.ts
Normal file
55
src/core/graph/subgraph/resolveSubgraphInputLink.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
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 from newest to oldest so the latest connection wins.
|
||||
for (let index = inputSlot.linkIds.length - 1; index >= 0; index -= 1) {
|
||||
const linkId = inputSlot.linkIds[index]
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user