fix: keep referenced subgraph definitions on unpack

- prevent subgraph definition deletion while other nodes still reference the same subgraph type

- stop unpack from force-deleting definitions after removing the unpacked node

- add regression coverage for unpacking one instance while another remains

Amp-Thread-ID: https://ampcode.com/threads/T-019c9e10-f581-7091-b103-05ec41896bda
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-02-27 00:24:14 -08:00
parent 02dd50a9a1
commit f781722f02

View File

@@ -1064,13 +1064,23 @@ export class LGraph
}
if (node.isSubgraphNode()) {
forEachNode(node.subgraph, (innerNode) => {
innerNode.onRemoved?.()
innerNode.graph?.onNodeRemoved?.(innerNode)
if (innerNode.isSubgraphNode())
this.rootGraph.subgraphs.delete(innerNode.subgraph.id)
})
this.rootGraph.subgraphs.delete(node.subgraph.id)
const allGraphs = [this.rootGraph, ...this.rootGraph.subgraphs.values()]
const hasRemainingReferences = allGraphs.some((graph) =>
graph.nodes.some(
(candidate) =>
candidate !== node &&
candidate.isSubgraphNode() &&
candidate.type === node.subgraph.id
)
)
if (!hasRemainingReferences) {
forEachNode(node.subgraph, (innerNode) => {
innerNode.onRemoved?.()
innerNode.graph?.onNodeRemoved?.(innerNode)
})
this.rootGraph.subgraphs.delete(node.subgraph.id)
}
}
// callback
@@ -1862,6 +1872,7 @@ export class LGraph
})
)
)
return { subgraph, node: subgraphNode as SubgraphNode }
}
@@ -2043,9 +2054,19 @@ export class LGraph
})
}
this.remove(subgraphNode)
this.subgraphs.delete(subgraphNode.subgraph.id)
// Deduplicate links by (oid, oslot, tid, tslot) to prevent repeated
// disconnect/reconnect cycles on widget inputs that can shift slot indices.
const seenLinks = new Set<string>()
const dedupedNewLinks = newLinks.filter((link) => {
const key = `${link.oid}:${link.oslot}:${link.tid}:${link.tslot}`
if (seenLinks.has(key)) return false
seenLinks.add(key)
return true
})
const linkIdMap = new Map<LinkId, LinkId[]>()
for (const newLink of newLinks) {
for (const newLink of dedupedNewLinks) {
let created: LLink | null | undefined
if (newLink.oid == SUBGRAPH_INPUT_ID) {
if (!(this instanceof Subgraph)) {
@@ -2319,7 +2340,6 @@ export class LGraph
const usedSubgraphs = [...this._subgraphs.values()]
.filter((subgraph) => usedSubgraphIds.has(subgraph.id))
.map((x) => x.asSerialisable())
if (usedSubgraphs.length > 0) {
data.definitions = { subgraphs: usedSubgraphs }
}