Skip to content

Commit a82a717

Browse files
committed
improvement(executor): dot-free names keep reference ownership on legacy collisions
Name uniqueness is enforced at the normalized level on create and rename, so new collisions cannot be created. For legacy workflows that already contain names differing only by dots, the resolver now lets the dot-free name own the reference key regardless of block order, so previously working references never change targets.
1 parent f4058b6 commit a82a717

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

apps/sim/executor/variables/resolvers/block.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,23 @@ describe('BlockResolver', () => {
254254
expect(resolver.resolve('<hunterio1.score>', ctx)).toBe(92)
255255
})
256256

257+
it.concurrent('should keep dot-free names as the reference target on legacy collisions', () => {
258+
const blocks = [
259+
{ id: 'block-dotted', name: 'Hunter.io 1' },
260+
{ id: 'block-plain', name: 'Hunterio 1' },
261+
]
262+
const ctx = createTestContext('current', {
263+
'block-dotted': { email: 'dotted@acme.com' },
264+
'block-plain': { email: 'plain@acme.com' },
265+
})
266+
267+
const resolver = new BlockResolver(createTestWorkflow(blocks))
268+
expect(resolver.resolve('<hunterio1.email>', ctx)).toBe('plain@acme.com')
269+
270+
const reversedResolver = new BlockResolver(createTestWorkflow([...blocks].reverse()))
271+
expect(reversedResolver.resolve('<hunterio1.email>', ctx)).toBe('plain@acme.com')
272+
})
273+
257274
it.concurrent('should resolve nested property path', () => {
258275
const workflow = createTestWorkflow([{ id: 'source' }])
259276
const resolver = new BlockResolver(workflow)

apps/sim/executor/variables/resolvers/block.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@ export class BlockResolver implements Resolver {
4343
for (const block of workflow.blocks) {
4444
this.blockById.set(block.id, block)
4545
if (block.metadata?.name) {
46-
this.nameToBlockId.set(normalizeName(block.metadata.name), block.id)
46+
// Name uniqueness is enforced at the normalized level on create/rename,
47+
// but legacy workflows may contain names that collide only now that
48+
// normalizeName strips dots. Dot-free names keep ownership of the key so
49+
// previously working references never change targets.
50+
const normalizedName = normalizeName(block.metadata.name)
51+
const incumbentId = this.nameToBlockId.get(normalizedName)
52+
const incumbentName = incumbentId
53+
? this.blockById.get(incumbentId)?.metadata?.name
54+
: undefined
55+
if (!incumbentId || incumbentName?.includes('.')) {
56+
this.nameToBlockId.set(normalizedName, block.id)
57+
}
4758
}
4859
}
4960
for (const loop of Object.values(workflow.loops ?? {})) {

0 commit comments

Comments
 (0)