diff --git a/packages/coding-agent/src/eval/js/context-manager.ts b/packages/coding-agent/src/eval/js/context-manager.ts index c03ebd1fb..5e67df8db 100644 --- a/packages/coding-agent/src/eval/js/context-manager.ts +++ b/packages/coding-agent/src/eval/js/context-manager.ts @@ -17,7 +17,7 @@ import type { WorkerOutbound, } from "./worker-protocol"; -export { rewriteImports } from "./shared/rewrite-imports"; +export { rewriteImports, wrapCode } from "./shared/rewrite-imports"; export type { JsDisplayOutput } from "./worker-protocol"; export interface VmRunState { diff --git a/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts b/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts index 84b9e50e7..f4f4f498e 100644 --- a/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts +++ b/packages/coding-agent/src/eval/js/shared/rewrite-imports.ts @@ -222,7 +222,11 @@ export function demoteTopLevelLexicals(code: string): string { function returnFinalExpression(code: string): { source: string; returned: boolean } { const ast = parseProgram(code); - const last = ast?.program.body.at(-1); + const body = ast?.program.body; + if (!body) return { source: code, returned: false }; + let lastIndex = body.length - 1; + while (lastIndex >= 0 && body[lastIndex]?.type === "EmptyStatement") lastIndex--; + const last = lastIndex >= 0 ? body[lastIndex] : undefined; if (last?.type !== "ExpressionStatement") return { source: code, returned: false }; const expression = last as BabelExpressionStatement; diff --git a/packages/coding-agent/test/core/js-static-import-rewrite.test.ts b/packages/coding-agent/test/core/js-static-import-rewrite.test.ts index 8ddadc3c4..2e85d78e5 100644 --- a/packages/coding-agent/test/core/js-static-import-rewrite.test.ts +++ b/packages/coding-agent/test/core/js-static-import-rewrite.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test"; -import { rewriteImports } from "../../src/eval/js/context-manager"; +import { rewriteImports, wrapCode } from "../../src/eval/js/context-manager"; // Test fixtures embed user-supplied `import(...)` syntax that the rewriter must // transform. The strings are split so static-analysis heuristics don't read them @@ -124,4 +124,10 @@ describe("rewriteImports", () => { // Should not throw; should fall through to the VM which will surface the syntax error. expect(() => rewriteImports(code)).not.toThrow(); }); + + it("captures the final expression even when trailing empty statements follow", () => { + const wrapped = wrapCode("await Promise.resolve(1);;"); + expect(wrapped.finalExpressionReturned).toBe(true); + expect(wrapped.source).toContain("__omp_set_final_expr__((await Promise.resolve(1)))"); + }); });