Skip to content

Conversation

@fraidev
Copy link
Contributor

@fraidev fraidev commented Jan 20, 2026

Closes #29876

  • tty.isatty() now returns false for negative and non-integer fd values
  • Added run_in_pty() to run pseudo-tty tests in a real terminal
  • Skip pseudo-tty tests on Windows CI where PTY is not supported
  • Enabled pseudo-tty/test-tty-isatty.js node compat test

@fraidev fraidev added the ci-draft Run the CI on draft PRs. label Jan 20, 2026
@fraidev fraidev changed the title Fix/node tty isatty integer validation fix(ext/node): validate fd is non-negative integer in tty.isatty() Jan 20, 2026
@fraidev fraidev force-pushed the fix/node-tty-isatty-integer-validation branch 2 times, most recently from bb85356 to 63ada3e Compare January 20, 2026 02:14
@fraidev fraidev force-pushed the fix/node-tty-isatty-integer-validation branch 3 times, most recently from b4f4f08 to 41e80bc Compare January 21, 2026 21:51
@fraidev fraidev changed the title fix(ext/node): validate fd is non-negative integer in tty.isatty() fix(ext/node): validate fd in tty.isatty and enable pseudo-tty tests Jan 21, 2026
@fraidev fraidev force-pushed the fix/node-tty-isatty-integer-validation branch from 41e80bc to 8ea451c Compare January 21, 2026 23:04
@fraidev fraidev marked this pull request as ready for review January 21, 2026 23:06
@fraidev fraidev removed the ci-draft Run the CI on draft PRs. label Jan 21, 2026
}

#[cfg(target_os = "windows")]
fn run_in_pty_impl(
Copy link
Member

Choose a reason for hiding this comment

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

I'm confused - weren't tests supposed to be skipped on Windows? If so then why do we need this impl?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should run on local Windows, just windows CI do not support PTY.

I didn't test on Windows locally, though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Screenshot 2026-01-21 at 20 57 48 I tested it on local Windows and is working fine.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes the tty.isatty() function to properly validate file descriptor values by returning false for negative and non-integer inputs, aligning with Node.js behavior. Additionally, it introduces PTY infrastructure to enable running pseudo-tty tests in real terminal environments.

Changes:

  • Fixed tty.isatty() to validate that fd is a non-negative integer using the same pattern as existing ReadStream/WriteStream constructors
  • Added comprehensive tests for the new validation behavior including negative and fractional fd values
  • Implemented run_in_pty() infrastructure for both Unix and Windows to execute tests in real PTY environments
  • Modified node_compat test runner to detect and execute pseudo-tty tests using the new PTY infrastructure
  • Enabled the pseudo-tty/test-tty-isatty.js test in the node compatibility test suite

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ext/node/polyfills/tty.js Added fd validation to check for non-negative integers in isatty()
tests/unit_node/tty_test.ts Added tests for negative and non-integer fd validation
tests/util/server/src/pty.rs Implemented run_in_pty() with PtyOutput struct for Unix and Windows platforms
tests/node_compat/mod.rs Added PTY detection and execution path for pseudo-tty tests
tests/node_compat/config.jsonc Enabled pseudo-tty/test-tty-isatty.js test

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 383 to 404
let mut child = unsafe {
std::process::Command::new(program)
.current_dir(cwd)
.args(args)
.envs(env_vars.unwrap_or_default())
.pre_exec(move || {
// Create a new session
libc::setsid();
// Set the controlling terminal
libc::ioctl(fds, libc::TIOCSCTTY as libc::c_ulong, 0);
set_winsize(fds, PTY_ROWS_COLS.0, PTY_ROWS_COLS.1)?;
// Close parent's main handle
libc::close(fdm);
libc::dup2(fds, 0);
libc::dup2(fds, 1);
libc::dup2(fds, 2);
libc::close(fds);
Ok(())
})
.spawn()
.unwrap()
};
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

If spawn() fails and panics on line 403, the file descriptors fdm and fds will be leaked. Consider using RAII guards (e.g., a custom struct with Drop implementation) or handling the error gracefully to ensure file descriptors are closed even on failure. While this is test infrastructure, proper cleanup would make debugging test failures easier.

Copilot uses AI. Check for mistakes.
@bartlomieju bartlomieju merged commit f321e88 into denoland:main Jan 22, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Node compat: tty.isatty() should only return true for positive integers

2 participants