fix: prevent blueprint cache corruption on repeated placement

Add structuredClone() in getBlueprint() so _deserializeItems() mutations
(node IDs, subgraph UUIDs) don't corrupt cached data.

Includes regression test verifying cache immutability.

Fixes COM-16026
This commit is contained in:
bymyself
2026-03-13 12:29:02 -07:00
parent db5e8961e0
commit 9bc9ea28b1
2 changed files with 11 additions and 1 deletions

View File

@@ -155,6 +155,16 @@ describe('useSubgraphStore', () => {
} as ComfyNodeDefV1)
expect(res).toBeTruthy()
})
it('should return a deep copy from getBlueprint so mutations do not corrupt the cache', async () => {
await mockFetch({ 'test.json': mockGraph })
const first = store.getBlueprint(store.typePrefix + 'test')
first.nodes[0].id = -1
first.definitions!.subgraphs![0].id = 'corrupted'
const second = store.getBlueprint(store.typePrefix + 'test')
expect(second.nodes[0].id).not.toBe(-1)
expect(second.definitions!.subgraphs![0].id).toBe('123')
})
it('should identify user blueprints as non-global', async () => {
await mockFetch({ 'test.json': mockGraph })
expect(store.isGlobalBlueprint('test')).toBe(false)

View File

@@ -392,7 +392,7 @@ export const useSubgraphStore = defineStore('subgraph', () => {
if (!(name in subgraphCache))
//As loading is blocked on in startup, this can likely be changed to invalid type
throw new Error('not yet loaded')
return subgraphCache[name].changeTracker.initialState
return structuredClone(subgraphCache[name].changeTracker.initialState)
}
async function deleteBlueprint(nodeType: string) {
const name = nodeType.slice(typePrefix.length)