diff --git a/src/main/browser/snapshot-engine.test.ts b/src/main/browser/snapshot-engine.test.ts index 17f5341b220..7282b432c1e 100644 --- a/src/main/browser/snapshot-engine.test.ts +++ b/src/main/browser/snapshot-engine.test.ts @@ -46,6 +46,25 @@ function node( } describe('buildSnapshot', () => { + it('keeps references routed to their own iframe session', async () => { + const tree = [ + node('1', 'WebArea', 'page', { childIds: ['2'] }), + node('2', 'button', 'Submit', { backendDOMNodeId: 10 }) + ] + const sessions = new Map([ + ['frame-a', 'session-a'], + ['frame-b', 'session-b'] + ]) + const result = await buildSnapshot(makeSender(tree), sessions, () => makeSender(tree)) + expect(result.refs.map((ref) => ref.ref)).toEqual(['@e1', '@e2', '@e3']) + expect([...result.refMap.values()].map((entry) => entry.sessionId)).toEqual([ + undefined, + 'session-a', + 'session-b' + ]) + expect([...result.refMap.values()].map((entry) => entry.backendDOMNodeId)).toEqual([10, 10, 10]) + }) + it('returns empty snapshot for empty tree', async () => { const result = await buildSnapshot(makeSender([])) expect(result.snapshot).toBe('') diff --git a/src/main/browser/snapshot-engine.ts b/src/main/browser/snapshot-engine.ts index 5cdabbc9375..fb0fe5e19dd 100644 --- a/src/main/browser/snapshot-engine.ts +++ b/src/main/browser/snapshot-engine.ts @@ -61,7 +61,7 @@ export async function buildSnapshot( // Why: cross-origin iframes have their own AX trees accessible only through // their dedicated CDP session. Append their elements after the parent tree // so the agent can see and interact with iframe content. - const iframeRefSessions: { ref: string; sessionId: string }[] = [] + const iframeRefSessions = new Map() if (iframeSessions && makeIframeSender && iframeSessions.size > 0) { for (const [_frameId, sessionId] of iframeSessions) { try { @@ -82,7 +82,7 @@ export async function buildSnapshot( const startRef = refCounter walkTree(iframeRoot, iframeNodeById, 1, entries, () => refCounter++) for (let i = startRef; i < refCounter; i++) { - iframeRefSessions.push({ ref: `@e${i}`, sessionId }) + iframeRefSessions.set(`@e${i}`, sessionId) } } } catch { @@ -120,12 +120,11 @@ export async function buildSnapshot( } lines.push(`${indent}[${entry.ref}] ${entry.role} "${displayName}"`) refs.push({ ref: entry.ref, role: entry.role, name: displayName }) - const iframeSession = iframeRefSessions.find((s) => s.ref === entry.ref) refMap.set(entry.ref, { backendDOMNodeId: entry.backendDOMNodeId, role: entry.role, name: entry.name, - sessionId: iframeSession?.sessionId, + sessionId: iframeRefSessions.get(entry.ref), nth: total > 1 ? nth : undefined }) } else {