What happened
When a conditional expression has await on one branch and a synchronous call on the other, Perry's codegen evaluates both branches at runtime, regardless of the condition.
What you expected
Only the branch matching the condition should be evaluated, matching JS/TS semantics.
Minimal reproduction
async function a(): Promise<number> { console.log('ran a'); return 1; }
function b(): number { console.log('ran b'); return 2; }
async function main(): Promise<void> {
const cmd: string = 'digest';
const r = cmd === 'fetch' ? await a() : b();
console.log('r=' + r);
process.exit(0);
}
main().catch((e) => { console.log(e); process.exit(1); });
Command:
perry compile repro.ts -o repro
./repro
Observed output:
Expected output (matches Node):
(Only b should run; cmd === 'fetch' is false.)
A purely-sync ternary cond ? a() : b() works correctly — only one branch runs. The bug is specific to await appearing on one side.
Workaround that works:
let r: number;
if (cmd === 'fetch') {
r = await a();
} else {
r = b();
}
Environment
- Perry version: 0.5.395
- Host OS: macOS 26.4 (arm64)
- Target: native
- Installed via: cargo (
~/.cargo/bin/perry)
Diagnostic output
No errors or warnings.
Found while compiling skelpo-listener: dispatching args.command === 'fetch' ? await runFetch(args) : runDigest(args) — under Perry, runFetch ran during a digest invocation, contaminating the digest output with fetch progress.
What happened
When a conditional expression has
awaiton one branch and a synchronous call on the other, Perry's codegen evaluates both branches at runtime, regardless of the condition.What you expected
Only the branch matching the condition should be evaluated, matching JS/TS semantics.
Minimal reproduction
Command:
Observed output:
Expected output (matches Node):
(Only
bshould run;cmd === 'fetch'is false.)A purely-sync ternary
cond ? a() : b()works correctly — only one branch runs. The bug is specific toawaitappearing on one side.Workaround that works:
Environment
~/.cargo/bin/perry)Diagnostic output
No errors or warnings.
Found while compiling skelpo-listener: dispatching
args.command === 'fetch' ? await runFetch(args) : runDigest(args)— under Perry,runFetchran during adigestinvocation, contaminating the digest output with fetch progress.