Skip to content

Commit 6cdb6b7

Browse files
christian-byrneampagent
authored andcommitted
fix(litegraph): clear widget and preview stores for the incoming graph id on configure
resetAfterClear() drops graph-scoped store entries under the id the graph held before configure, then _configureBase() adopts the payload's id. Any entry still held for the incoming id therefore outlives the reload, and a node re-adopts it instead of reading the payload. configure() already re-clears link, reroute and node-data state for the incoming id; widgetValueStore and previewExposureStore were missing from that block.
1 parent 7ec4ffc commit 6cdb6b7

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { describe, expect, test } from 'vitest'
2+
3+
import { LGraph, LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph'
4+
import { usePreviewExposureStore } from '@/stores/previewExposureStore'
5+
import { renameWidget } from '@/utils/widgetUtil'
6+
7+
class LabelledWidgetNode extends LGraphNode {
8+
static override title = 'LabelledWidget'
9+
constructor() {
10+
super('LabelledWidget')
11+
this.serialize_widgets = true
12+
this.addWidget('text', 'text', 'a cat', null)
13+
const input = this.addInput('text', 'STRING')
14+
input.widget = { name: 'text' }
15+
}
16+
}
17+
18+
LiteGraph.registerNodeType('test/LabelledWidget', LabelledWidgetNode)
19+
20+
/**
21+
* `configure` adopts the payload's graph id (`_configureBase`), while `clear`
22+
* only drops store entries keyed by the id the graph held *before* configure.
23+
* Anything the graph-id-keyed stores still hold for the incoming id therefore
24+
* outlives the reload and is re-adopted instead of being read from the payload.
25+
*/
26+
describe('LGraph.configure clears graph-scoped stores for the incoming id', () => {
27+
function addLabelledNode(graph: LGraph, label: string) {
28+
const node = LiteGraph.createNode('test/LabelledWidget')!
29+
graph.add(node)
30+
renameWidget(node.widgets![0], node, label)
31+
return node
32+
}
33+
34+
function createSourceGraph() {
35+
const graph = new LGraph()
36+
const node = addLabelledNode(graph, 'Live Label')
37+
return { graph, node }
38+
}
39+
40+
test('a reloaded widget label is read from the payload, never inherited from the live store', () => {
41+
const graph = new LGraph()
42+
const dropped = addLabelledNode(graph, 'Dropped Label')
43+
const kept = addLabelledNode(graph, 'Kept Label')
44+
45+
const payload = JSON.parse(JSON.stringify(graph.serialize()))
46+
const droppedData = payload.nodes.find(
47+
(n: { id: unknown }) => String(n.id) === String(dropped.id)
48+
)
49+
delete droppedData.inputs[0].label
50+
51+
const restored = new LGraph()
52+
restored.configure(payload)
53+
54+
expect(restored.id).toBe(graph.id)
55+
expect(restored.getNodeById(dropped.id)!.widgets![0].label).toBeUndefined()
56+
expect(restored.getNodeById(kept.id)!.widgets![0].label).toBe('Kept Label')
57+
})
58+
59+
test('preview exposures held for the incoming id do not survive the reload', () => {
60+
const { graph } = createSourceGraph()
61+
const store = usePreviewExposureStore()
62+
store.setExposures(graph.id, '99', [
63+
{ sourceNodeId: '1', sourcePreviewName: 'preview', name: 'preview' }
64+
])
65+
66+
const payload = JSON.parse(JSON.stringify(graph.serialize()))
67+
68+
const restored = new LGraph()
69+
restored.configure(payload)
70+
71+
expect(restored.id).toBe(graph.id)
72+
expect(store.getExposures(restored.id, '99')).toEqual([])
73+
})
74+
})

src/lib/litegraph/src/LGraph.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,6 +2608,8 @@ export class LGraph
26082608
useLinkStore().clearGraph(topologyScope.rootGraphId)
26092609
useRerouteStore().clearGraph(topologyScope.rootGraphId)
26102610
useNodeDataStore().clearGraph(this.id)
2611+
useWidgetValueStore().clearGraph(this.id)
2612+
usePreviewExposureStore().clearGraph(this.id)
26112613
} else {
26122614
useLinkStore().clearOwner(topologyScope)
26132615
useRerouteStore().clearOwner(topologyScope)

0 commit comments

Comments
 (0)