Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/jsc/bindings/wtf-bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ extern "C" int uv_tty_reset_mode(void)

static void uv__tty_make_raw(struct termios* tio)
{
assert(tio != NULL);
ASSERT(tio != NULL);

#if defined __sun || defined __MVS__
/*
Expand Down
26 changes: 26 additions & 0 deletions test/js/bun/terminal/terminal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,32 @@

expect(() => terminal.setRawMode(true)).toThrow("Terminal is closed");
});

// Regression for #30988: wtf-bindings.cpp used libc `assert` without
// including <cassert>. After the WebKit upgrade in #30705 the header
// stopped reaching this translation unit transitively, so debug builds
// failed to compile. Building and running this test file exercises
// Bun__ttySetMode (the same translation unit) on a real PTY fd and
// proves the file compiled.
test.skipIf(isWindows)("setRawMode toggles on a real PTY fd", async () => {
await using terminal = new Bun.Terminal({});
const ICANON = 0x2;

Check failure on line 290 in test/js/bun/terminal/terminal.test.ts

View check run for this annotation

Claude / Claude Code Review

Hardcoded ICANON=0x2 is wrong on macOS — test will fail in macOS CI

The hardcoded `const ICANON = 0x2` is the Linux value; on macOS/BSD, `ICANON` is `0x100` and bit `0x2` is `ECHOE`. Since `Bun__ttySetMode` mode=1 clears `~(ECHO | ICANON | IEXTEN | ISIG)` but not `ECHOE` (which Terminal init sets to true), `expect(rawLflag & ICANON).toBe(0)` will fail on macOS CI. Use `isMacOS ? 0x100 : 0x2`, mirroring the existing PENDIN special-casing in this file.
Comment thread
robobun marked this conversation as resolved.
Outdated
const ECHO = 0x8;

const beforeLflag = terminal.localFlags;
expect(beforeLflag & ICANON).not.toBe(0);
expect(beforeLflag & ECHO).not.toBe(0);

terminal.setRawMode(true);
const rawLflag = terminal.localFlags;
expect(rawLflag & ICANON).toBe(0);
expect(rawLflag & ECHO).toBe(0);

terminal.setRawMode(false);
const restoredLflag = terminal.localFlags;
expect(restoredLflag & ICANON).not.toBe(0);
expect(restoredLflag & ECHO).not.toBe(0);
});
Comment on lines +296 to +309
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check default ECHO flag state in Bun.Terminal on POSIX

bun -e '
const t = new Bun.Terminal({});
const ECHO = 0x8;
const echoEnabled = (t.localFlags & ECHO) !== 0;
console.log("ECHO enabled by default:", echoEnabled);
t.close();
'

Repository: oven-sh/bun

Length of output: 99


🏁 Script executed:

cd /tmp && wc -l test/js/bun/terminal/terminal.test.ts 2>/dev/null || find . -path "*test/js/bun/terminal*" -name "*.ts" 2>/dev/null

Repository: oven-sh/bun

Length of output: 37


🏁 Script executed:

head -20 test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 769


🏁 Script executed:

# Check the enableEcho helper and surrounding context (lines 1-10)
sed -n '1,20p' test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 769


🏁 Script executed:

# Read the entire test file to verify the claims
cat test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 35985


🏁 Script executed:

# Let's search for the enableEcho function and its usages
rg -n "enableEcho" test/js/bun/terminal/terminal.test.ts -A 2 -B 2

Repository: oven-sh/bun

Length of output: 1367


🏁 Script executed:

# Also check for ECHO and ICANON constants
rg -n "const ECHO|const ICANON" test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 198


🏁 Script executed:

# Check lines 290-315 for the disputed test
sed -n '290,315p' test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 999


🏁 Script executed:

# Read specific line ranges
head -30 test/js/bun/terminal/terminal.test.ts

Repository: oven-sh/bun

Length of output: 992


🏁 Script executed:

cat -n test/js/bun/terminal/terminal.test.ts | sed -n '1,50p'

Repository: oven-sh/bun

Length of output: 1766


🏁 Script executed:

python3 << 'EOF'
import os
filepath = 'test/js/bun/terminal/terminal.test.ts'
if os.path.exists(filepath):
    with open(filepath, 'r') as f:
        lines = f.readlines()
        print(f"Total lines: {len(lines)}")
        # Show lines 1-20
        print("\n=== Lines 1-20 ===")
        for i in range(min(20, len(lines))):
            print(f"{i+1:3d}: {lines[i]}", end='')
else:
    print(f"File not found: {filepath}")
EOF

Repository: oven-sh/bun

Length of output: 907


🏁 Script executed:

git ls-files | grep terminal | grep test

Repository: oven-sh/bun

Length of output: 189


🏁 Script executed:

ls -la test/js/bun/ 2>&1 | head -20

Repository: oven-sh/bun

Length of output: 1221


🏁 Script executed:

# Check if the directory exists
ls -d test/js/bun/terminal 2>&1 || echo "Directory not found"
# List all test files
ls test/js/bun/*.test.ts 2>&1 | head

Repository: oven-sh/bun

Length of output: 350


🏁 Script executed:

# Search for the test mentioned in the review
rg "setRawMode" . --type ts --type tsx -l

Repository: oven-sh/bun

Length of output: 83


🏁 Script executed:

# Find all test files with "terminal" in the name
find . -name "*terminal*" 2>/dev/null | grep -E "\.(ts|tsx|js)$"

Repository: oven-sh/bun

Length of output: 195


🏁 Script executed:

# Also search for ECHO constant definitions
rg "const ECHO" --type ts --type tsx

Repository: oven-sh/bun

Length of output: 83


🏁 Script executed:

# Check if there's a Bun.Terminal test file
rg "Bun.Terminal" test --type ts --type tsx -l

Repository: oven-sh/bun

Length of output: 83


🏁 Script executed:

# Try to find any reference to the Terminal class or test
rg "class.*Terminal|function.*Terminal|new.*Terminal" test --type ts --type tsx -l | head

Repository: oven-sh/bun

Length of output: 83


🏁 Script executed:

# Search for any Terminal-related test
fd -e test.ts -e test.tsx -e test.js test/ | xargs grep -l "Terminal" 2>/dev/null | head

Repository: oven-sh/bun

Length of output: 381


Verify ECHO flag initial state—contradicts existing helper documentation.

Lines 298 and 308 assert that the ECHO flag is enabled in the default terminal state and after disabling raw mode:

expect(beforeLflag & ECHO).not.toBe(0);  // expects ECHO enabled initially
...
expect(restoredLflag & ECHO).not.toBe(0); // expects ECHO enabled after restore

However, the enableEcho helper (line 4) documents that "echo is disabled by default to avoid duplication", and all existing tests explicitly call enableEcho(terminal) before exercising echo behavior (e.g., lines 483, 507, 532, 553, 571, 776, 829, 945), confirming that Bun.Terminal initializes with ECHO off.

The test should instead expect:

expect(beforeLflag & ECHO).toBe(0);      // ECHO disabled initially
expect(rawLflag & ECHO).toBe(0);         // ECHO still disabled in raw mode
expect(restoredLflag & ECHO).toBe(0);    // ECHO remains disabled after restore

While the test's primary goal (proving wtf-bindings.cpp compiled by exercising Bun__ttySetMode on a real PTY fd) is sound, these incorrect assertions will cause spurious test failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/js/bun/terminal/terminal.test.ts` around lines 296 - 309, The assertions
about the ECHO bit are incorrect given that Bun.Terminal initializes with echo
off; update the expectations in the test around terminal.localFlags so they
assert ECHO is cleared (toBe(0)) for beforeLflag, rawLflag, and restoredLflag
instead of asserting it is set, leaving the ICANON checks unchanged; locate the
assertions near the calls to terminal.setRawMode(true)/setRawMode(false) and
adjust the three expect(... & ECHO) lines accordingly (references:
terminal.localFlags, terminal.setRawMode, constants ICANON and ECHO, helper
enableEcho).

});

describe("termios flags", () => {
Expand Down
Loading