fix(code-mode): keep deep host boundaries iterative

This commit is contained in:
Tianyi Cui
2026-07-23 00:30:36 +08:00
parent 25d0ef5c6c
commit e35a419ba8
8 changed files with 144 additions and 21 deletions
+24 -8
View File
@@ -58,7 +58,8 @@ export function isAgentLoopRequest(request: GenerateOptions): boolean {
}
/**
* Deep-freeze a value in place, guarding cycles, so later mutation throws.
* Deep-freeze a value in place with an iterative traversal, guarding cycles,
* so later mutation throws without imposing a JavaScript call-stack depth cap.
* {@link AbortSignal} objects are deliberately skipped because they are the
* request's live cancellation channel and freezing them breaks abort.
* @param value - the value to freeze in place.
@@ -66,16 +67,31 @@ export function isAgentLoopRequest(request: GenerateOptions): boolean {
*/
export function deepFreeze<T>(value: T): T {
const seen = new WeakSet<object>()
const walk = (node: unknown): void => {
if (node === null || typeof node !== 'object') return
if (node instanceof AbortSignal) return
if (seen.has(node)) return
const pending: (
| { kind: 'visit'; node: unknown }
| { kind: 'property'; source: Record<string, unknown>; key: string }
)[] = [{ kind: 'visit', node: value }]
while (pending.length > 0) {
const task = pending.pop()
/* v8 ignore next -- the loop condition guarantees one pending task. */
if (task === undefined) continue
if (task.kind === 'property') {
pending.push({ kind: 'visit', node: task.source[task.key] })
continue
}
const node = task.node
if (node === null || typeof node !== 'object') continue
if (node instanceof AbortSignal) continue
if (seen.has(node)) continue
seen.add(node)
Object.freeze(node)
for (const key of Object.keys(node)) {
walk((node as Record<string, unknown>)[key])
const keys = Object.keys(node)
for (let index = keys.length - 1; index >= 0; index--) {
const key = keys[index]
/* v8 ignore next -- the loop is bounded by the captured key count. */
if (key === undefined) continue
pending.push({ kind: 'property', source: node as Record<string, unknown>, key })
}
}
walk(value)
return value
}
@@ -56,6 +56,26 @@ describe('deepFreeze', () => {
deepFreeze(cyclic)
expect(Object.isFrozen(cyclic)).toBe(true)
})
it('freezes nesting deeper than the JavaScript call stack', () => {
const depth = 5_000
const root: unknown[] = []
let cursor = root
for (let index = 0; index < depth; index++) {
const child: unknown[] = []
cursor.push(child)
cursor = child
}
deepFreeze(root)
cursor = root
for (let index = 0; index < depth; index++) {
expect(Object.isFrozen(cursor)).toBe(true)
cursor = cursor[0] as unknown[]
}
expect(Object.isFrozen(cursor)).toBe(true)
})
})
describe('agent-loop request identity', () => {