Fix link corruption (#888)

- Adds link & floating link integrity tests to all LinkConnector
integration tests
- Fixes link changes may be lost when moving floating links
This commit is contained in:
filtered
2025-04-05 16:34:55 +11:00
committed by GitHub
parent c4373deeea
commit 64c7113440
3 changed files with 56 additions and 2 deletions

View File

@@ -329,6 +329,35 @@ export class Reroute implements Positionable, LinkSegment, Serialisable<Serialis
return out
}
/**
* Changes the origin node/output of all floating links that pass through this reroute.
* @param node The new origin node
* @param output The new origin output slot
* @param index The slot index of {@link output}
*/
setFloatingLinkOrigin(node: LGraphNode, output: INodeOutputSlot, index: number) {
const network = this.#network.deref()
const floatingOutLinks = this.getFloatingLinks("output")
if (!floatingOutLinks) throw new Error("[setFloatingLinkOrigin]: Invalid network.")
if (!floatingOutLinks.length) return
output._floatingLinks ??= new Set()
for (const link of floatingOutLinks) {
// Update cached floating links
output._floatingLinks.add(link)
network?.getNodeById(link.origin_id)
?.outputs[link.origin_slot]
?._floatingLinks
?.delete(link)
// Update the floating link
link.origin_id = node.id
link.origin_slot = index
}
}
/** @inheritdoc */
move(deltaX: number, deltaY: number) {
this.#pos[0] += deltaX

View File

@@ -392,11 +392,13 @@ export class LinkConnector {
const originalReroutes = maybeReroutes.slice(0, -1).reverse()
// From reroute to reroute
if (this.renderLinks.length === 1 && renderLink instanceof ToInputRenderLink) {
const { node, fromSlotIndex, fromReroute } = renderLink
if (renderLink instanceof ToInputRenderLink) {
const { node, fromSlot, fromSlotIndex, fromReroute } = renderLink
const floatingOutLinks = reroute.getFloatingLinks("output")
const floatingInLinks = reroute.getFloatingLinks("input")
reroute.setFloatingLinkOrigin(node, fromSlot, fromSlotIndex)
// Clean floating link IDs from reroutes about to be removed from the chain
if (floatingOutLinks && floatingInLinks) {
for (const link of floatingOutLinks) {

View File

@@ -121,6 +121,29 @@ const test = baseTest.extend<TestContext>({
}
}
}
for (const link of graph._links.values()) {
expect(graph.getNodeById(link!.origin_id)?.outputs[link!.origin_slot].links).toContain(link.id)
expect(graph.getNodeById(link!.target_id)?.inputs[link!.target_slot].link).toBe(link.id)
}
for (const link of graph.floatingLinks.values()) {
if (link.target_id === -1) {
expect(link.origin_id).not.toBe(-1)
expect(link.origin_slot).not.toBe(-1)
expect(link.target_slot).toBe(-1)
const outputFloatingLinks = graph.getNodeById(link.origin_id)?.outputs[link.origin_slot]._floatingLinks
expect(outputFloatingLinks).toBeDefined()
expect(outputFloatingLinks).toContain(link)
} else {
expect(link.origin_id).toBe(-1)
expect(link.origin_slot).toBe(-1)
expect(link.target_slot).not.toBe(-1)
const inputFloatingLinks = graph.getNodeById(link.target_id)?.inputs[link.target_slot]._floatingLinks
expect(inputFloatingLinks).toBeDefined()
expect(inputFloatingLinks).toContain(link)
}
}
})
},