
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
This is an addon that adds a PTY layer to xterm.js. It is useful to run an Emscripten'ed CUI program.
See the demo site: https://xterm-pty.netlify.app/.
If you want to use this library to run a CUI program built with Emscripten, you can go to Section "Emscripten integration".
Install xterm-pty as usual.
npm i xterm-pty
Use LineDisciplineAddon.write and LineDisciplineAddon.onData instead of Terminal.write and Terminal.onData of xterm.js.
// Start an xterm.js instance
const xterm = new Terminal();
// Create master/slave objects
const { master, slave } = openpty();
// Connect the master object to xterm.js
xterm.loadAddon(master);
// Use slave.write instead of xterm.write
slave.write("Hello, world!\nInput your name:");
// Use slave.onReadable and slave.read instead of xterm.onData
slave.onReadable(() => {
xterm.write(`Hi, ${ slave.read().trim() }!\n`);
});
Result:
Hello, world!
Input your name: Yusuke
Hi, Yusuke!
■
Reading user input (e.g. via functions like fgets) requires pausing the WebAssembly app.
We can't block the main thread as that will prevent any events, including user input, from waking the application and causing the deadlock. Instead, we support two modes of asynchronous pausing via corresponding Emscripten features.
You can compile your application with -pthread -s PROXY_TO_PTHREAD. In this mode Emscripten will transparently move your application to run in a pthread (in a Web Worker).
xterm-pty will use proxying to read from and write to the Xterm.js terminal on the main thread and pause the "main" pthread until results are received.
In this mode, any written content will be flushed to the screen as soon as possible, regardless of whether the proxied pthread is blocked or not, which makes it particularly useful for running applications that write content non-stop, such as the Sloane demo.
However, if your application needs direct access to DOM via Embind or custom JavaScript, you'll need more work to proxy those operations yourself as Web Workers don't have direct access to the DOM.
Also, PThreads rely on SharedArrayBuffer and atomics, which is a relatively new feature and might be not available in older browsers. It also requires that you serve your application with the cross-origin isolation headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
See this explainer for more details on these headers.
If you want your application running on the main thread, you can instead compile it with -s ASYNCIFY.
In this mode Emscripten will rewrite the WebAssembly application, making it behave as one large async-await function. This allows asynchronous pausing right on the main thread without actually blocking it.
One downside is that it currently adds a noticeable size overhead to the resulting WebAssembly binary.
Another is that, for performance reasons, we'll only automatically pause to read user input (e.g. via fgets) and not to flush any output, so if your application writes a lot of output non-stop like the earlier mentioned Sloane demo, you won't see it appear on the screen until you manually pause the application with e.g. emscripten_sleep(0).
Assume you want to run example.c in xterm.js.
Compile it with Emscripten with either -s ASYNCIFY or -s PROXY_TO_PTHREAD.
Include xterm-pty's Emscripten integration library via --js-library=[path to xterm-pty]/emscripten-pty.js. We'll use ES6 module output as that's the easiest way to pass some options to the generated Emscripten Module, but feel free to use any other output format.
emcc -s ASYNCIFY --js-library=node_modules/xterm-pty/emscripten-pty.js -o example.mjs example.c
This will generate two files, example.mjs and example.wasm.
Write a HTML as follows.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/xterm@5.3.0/css/xterm.css" />
</head>
<body>
<div id="terminal"></div>
<script type="module">
import 'https://unpkg.com/xterm@5.3.0/lib/xterm.js';
import 'https://unpkg.com/xterm-pty/index.js';
import initEmscripten from './example.mjs';
var xterm = new Terminal();
xterm.open(document.getElementById('terminal'));
// Create master/slave objects
const { master, slave } = openpty();
// Connect the master object to xterm.js
xterm.loadAddon(master);
await initEmscripten({
pty: slave
});
</script>
</body>
</html>
Currently, Emscripten integration library patches the Emscripten runtime functions to intercept TTY access.
fd_read to pause on reads from the file descriptor 0ioctl_* for TCGETS (getting termios), TCSETS and families (setting termios), and TIOCGWINSZ (gettins window size)poll and newselect syscalls to pause while waiting for stdin to become readableIt also sends terminal signals to the Emscripten'd application so that Ctrl+C for termination or terminal resizing should work as expected.
The integration hack highly depends on the internal implementation of the Emscripten runtime. It's confirmed to work with Emscripten 3.1.47, which can be installed via emsdk install 3.1.47.
From xterm.js to the Emscripten runtime:
graph TB
A(xterm.js) -->|Terminal.onData| B[PTY Master]
subgraph "PTY"
B -->|LineDiscipline.writeFromLower| C[LineDiscipline]
C -->|LineDiscipline.onWriteToUpper| D[PTY Slave]
end
subgraph "emcc-generated code"
D -->|Slave.read| E[emscripten-pty.js]
E -->|overridden read syscall| F[Emscripten runtime]
end
From the Emscripten runtime to xterm.js:
graph BT
B[PTY Master] -->|Terminal.write| A(xterm.js)
subgraph "PTY"
C[LineDiscipline] -->|LineDiscipline.onWriteToLower| B
D[PTY Slave] -->|LineDiscipline.writeFromUpper| C
end
subgraph "emcc-generated code"
E[emscripten-pty.js] -->|Slave.write| D
F[Emscripten runtime] -->|overridden write syscall| E
end
To build xterm-pty, run:
npm install && npm run build
To build the demo, run:
cd demo && npm install && npm run build
To preview the demo after editing xterm-pty, the following command is useful.
cd `git rev-parse --show-toplevel` && npm run build && cd demo && rm -rf node_modules/ && npm install && npm run dev
FAQs
A pty for xterm.js and Emscripten
The npm package xterm-pty receives a total of 160 weekly downloads. As such, xterm-pty popularity was classified as not popular.
We found that xterm-pty demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.