Skip to content

Commit 2fdd8f2

Browse files
committed
programs-react: lock inline reconstruction against bracketed + smeared shapes (#239)
Add fixtures for both emission shapes the reconstruction must handle: - bracketed (post #235): invoke on the body's first op, return on the last, transform:["inline"] on all — frame visible across every body op INCLUDING the exit op (close-after), gone at the gap. - legacy smeared: every op carries invoke+return+inline — close-after still yields exactly one frame per body, no accumulation across gap-separated bodies. Verified end-to-end on real O2 (dbl@2 sites, #235 bracketed emission): one virtual frame per body incl. the exit op, top level between/after.
1 parent a87c5b0 commit 2fdd8f2

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

‎packages/programs-react/src/utils/mockTrace.test.ts‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,4 +611,97 @@ describe("inline virtual activations", () => {
611611
expect(buildCallStack(trace, pcToInstruction, 3)).toHaveLength(0);
612612
});
613613
});
614+
615+
describe("bracketed emission (post de-smear, #235 shape)", () => {
616+
// The real bracketed shape: invoke on the body's FIRST op,
617+
// return on its LAST op, transform:["inline"] on every op. The
618+
// frame must be visible across the whole body — including the
619+
// return-bearing exit op (close-after) — and gone at the gap.
620+
const entryOp = {
621+
transform: ["inline"],
622+
invoke: { jump: true, identifier: "dbl" },
623+
};
624+
const interiorOp = { transform: ["inline"] };
625+
const exitOp = { transform: ["inline"], return: { identifier: "dbl" } };
626+
const gapOp = { code: { source: { id: "0" }, range: {} } };
627+
const trace: TraceStep[] = [
628+
{ pc: 0, opcode: "PUSH1" }, // entry op (invoke)
629+
{ pc: 1, opcode: "DUP2" }, // interior op
630+
{ pc: 2, opcode: "ADD" }, // interior op
631+
{ pc: 3, opcode: "MSTORE" }, // exit op (return)
632+
{ pc: 4, opcode: "JUMPDEST" }, // gap / caller
633+
];
634+
const program = {
635+
instructions: [
636+
instr(0, entryOp),
637+
instr(1, interiorOp),
638+
instr(2, interiorOp),
639+
instr(3, exitOp),
640+
instr(4, gapOp),
641+
],
642+
} as unknown as Program;
643+
const pcToInstruction = buildPcToInstructionMap(program);
644+
645+
it("shows the virtual frame across every body op incl. the exit", () => {
646+
for (const s of [0, 1, 2, 3]) {
647+
const stack = buildCallStack(trace, pcToInstruction, s);
648+
expect(stack).toHaveLength(1);
649+
expect(stack[0].isInline).toBe(true);
650+
}
651+
});
652+
653+
it("is gone at the gap after the return op", () => {
654+
expect(buildCallStack(trace, pcToInstruction, 4)).toHaveLength(0);
655+
});
656+
});
657+
658+
describe("robustness: legacy SMEARED emission (pre de-smear)", () => {
659+
// Belt-and-suspenders: an older/residual emission where EVERY
660+
// body op carries invoke+return+inline. Close-after must still
661+
// yield exactly one frame per body across all ops (the viewed
662+
// op's co-located return is deferred; prior ops net empty) and
663+
// no accumulation across two gap-separated bodies.
664+
const smearedOp = {
665+
transform: ["inline"],
666+
invoke: { jump: true, identifier: "dbl" },
667+
return: { identifier: "dbl" },
668+
};
669+
const gapOp = { code: { source: { id: "0" }, range: {} } };
670+
const trace: TraceStep[] = [
671+
{ pc: 0, opcode: "PUSH1" }, // body 1: 3 smeared ops
672+
{ pc: 1, opcode: "DUP2" },
673+
{ pc: 2, opcode: "MSTORE" },
674+
{ pc: 3, opcode: "JUMPDEST" }, // gap
675+
{ pc: 4, opcode: "PUSH1" }, // body 2: 3 smeared ops
676+
{ pc: 5, opcode: "DUP2" },
677+
{ pc: 6, opcode: "MSTORE" },
678+
{ pc: 7, opcode: "JUMPDEST" }, // gap
679+
];
680+
const program = {
681+
instructions: [
682+
instr(0, smearedOp),
683+
instr(1, smearedOp),
684+
instr(2, smearedOp),
685+
instr(3, gapOp),
686+
instr(4, smearedOp),
687+
instr(5, smearedOp),
688+
instr(6, smearedOp),
689+
instr(7, gapOp),
690+
],
691+
} as unknown as Program;
692+
const pcToInstruction = buildPcToInstructionMap(program);
693+
694+
it("shows exactly one frame across each smeared body", () => {
695+
for (const s of [0, 1, 2, 4, 5, 6]) {
696+
const stack = buildCallStack(trace, pcToInstruction, s);
697+
expect(stack).toHaveLength(1);
698+
expect(stack[0].isInline).toBe(true);
699+
}
700+
});
701+
702+
it("returns to top level at each gap — no accumulation", () => {
703+
expect(buildCallStack(trace, pcToInstruction, 3)).toHaveLength(0);
704+
expect(buildCallStack(trace, pcToInstruction, 7)).toHaveLength(0);
705+
});
706+
});
614707
});

0 commit comments

Comments
 (0)