MCPcopy Create free account
hub / github.com/Comfy-Org/litegraph.js / resolveOutput

Method resolveOutput

src/subgraph/ExecutableNodeDTO.ts:203–263  ·  view source on GitHub ↗

* Determines whether this output is a valid endpoint for a link (non-virtual, non-bypass). * @param slot The slot index of the output. * @param type The type of the input * @param visited A set of unique IDs to guard against infinite recursion. See resolveInput. * @returns The no

(slot: number, type: ISlotType, visited: Set<string>)

Source from the content-addressed store, hash-verified

201 * @returns The node and the origin ID / slot index of the output.
202 */
203 resolveOutput(slot: number, type: ISlotType, visited: Set<string>): ResolvedInput | undefined {
204 const uniqueId = `${this.subgraphNode?.subgraph.id}:${this.node.id}[O]${slot}`
205 if (visited.has(uniqueId)) {
206 const nodeInfo = `${this.node.id}${this.node.title ? ` (${this.node.title})` : ""}`
207 const pathInfo = this.subgraphNodePath.length > 0 ? ` at path ${this.subgraphNodePath.join(":")}` : ""
208 throw new RecursionError(
209 `Circular reference detected while resolving output ${slot} of node ${nodeInfo}${pathInfo}. ` +
210 `This creates an infinite loop in link resolution. UniqueID: [${uniqueId}]`,
211 )
212 }
213 visited.add(uniqueId)
214
215 // Upstreamed: Bypass nodes are bypassed using the first input with matching type
216 if (this.mode === LGraphEventMode.BYPASS) {
217 const { inputs } = this
218
219 // Bypass nodes by finding first input with matching type
220 const parentInputIndexes = Object.keys(inputs).map(Number)
221 // Prioritise exact slot index
222 const indexes = [slot, ...parentInputIndexes]
223 const matchingIndex = indexes.find(i => inputs[i]?.type === type)
224
225 // No input types match
226 if (matchingIndex === undefined) {
227 console.debug(`[ExecutableNodeDTO.resolveOutput] No input types match type [${type}] for id [${this.id}] slot [${slot}]`, this)
228 return
229 }
230
231 return this.resolveInput(matchingIndex, visited)
232 }
233
234 const { node } = this
235 if (node.isSubgraphNode()) return this.#resolveSubgraphOutput(slot, type, visited)
236
237 // Upstreamed: Other virtual nodes are bypassed using the same input/output index (slots must match)
238 if (node.isVirtualNode) {
239 if (this.inputs.at(slot)) return this.resolveInput(slot, visited)
240
241 // Fallback check for nodes performing link redirection
242 const virtualLink = this.node.getInputLink(slot)
243 if (virtualLink) {
244 const outputNode = this.graph.getNodeById(virtualLink.origin_id)
245 if (!outputNode) throw new InvalidLinkError(`Virtual node failed to resolve parent [${this.id}] slot [${slot}]`)
246
247 const outputNodeExecutionId = [...this.subgraphNodePath, outputNode.id].join(":")
248 const outputNodeDto = this.nodesByExecutionId.get(outputNodeExecutionId)
249 if (!outputNodeDto) throw new Error(`No output node DTO found for id [${outputNode.id}]`)
250
251 return outputNodeDto.resolveOutput(virtualLink.origin_slot, type, visited)
252 }
253
254 // Virtual nodes without a matching input should be discarded.
255 return
256 }
257
258 return {
259 node: this,
260 origin_id: this.id,

Callers 3

resolveInputMethod · 0.80

Calls 8

resolveInputMethod · 0.95
hasMethod · 0.80
addMethod · 0.80
getMethod · 0.80
getNodeByIdMethod · 0.65
isSubgraphNodeMethod · 0.45
getInputLinkMethod · 0.45

Tested by

no test coverage detected