mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
## Summary - Fix transpiler bug where comma expressions like `(0, obj.method)()` were incorrectly optimized to `obj.method()` - This preserved the `this` binding instead of stripping it as per JavaScript semantics - Add comprehensive regression test to prevent future issues ## Root Cause The comma operator optimization in `src/js_parser.zig:7281` was directly returning the right operand when the left operand had no side effects, without checking if the expression was being used as a call target. ## Solution - Added the same `is_call_target` check that other operators (nullish coalescing, logical OR/AND) use - When a comma expression is used as a call target AND the right operand has a value for `this`, preserve the comma expression to strip the `this` binding - Follows existing patterns in the codebase for consistent behavior ## Test Plan - [x] Reproduce the original bug: `(0, obj.method)()` incorrectly preserved `this` - [x] Verify fix: comma expressions now correctly strip `this` binding in function calls - [x] All existing transpiler tests continue to pass - [x] Added regression test covering various comma expression scenarios - [x] Tested edge cases: nested comma expressions, side effects, different operand types 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
45 lines
1.1 KiB
TypeScript
45 lines
1.1 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
|
|
|
test("comma operator should strip 'this' binding in function calls", async () => {
|
|
const dir = tempDirWithFiles("comma-operator-test", {
|
|
"test.js": `
|
|
const doThing = () => {};
|
|
|
|
const cool = {
|
|
value: "beans",
|
|
logValue() {
|
|
console.log(this?.value || "undefined");
|
|
}
|
|
}
|
|
|
|
// Direct call - should preserve 'this'
|
|
cool.logValue();
|
|
|
|
// Comma operator calls - should strip 'this'
|
|
(0, cool.logValue)();
|
|
(doThing(), cool.logValue)();
|
|
`,
|
|
});
|
|
|
|
await using proc = Bun.spawn({
|
|
cmd: [bunExe(), "test.js"],
|
|
env: bunEnv,
|
|
cwd: dir,
|
|
stderr: "pipe",
|
|
stdout: "pipe",
|
|
});
|
|
|
|
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
|
|
|
|
expect(exitCode).toBe(0);
|
|
expect(stderr).toBe("");
|
|
|
|
// Should output: beans, undefined, undefined
|
|
const lines = stdout.trim().split("\n");
|
|
expect(lines).toHaveLength(3);
|
|
expect(lines[0]).toBe("beans");
|
|
expect(lines[1]).toBe("undefined");
|
|
expect(lines[2]).toBe("undefined");
|
|
});
|