MIRROR: javascript for 🐜's, a tiny runtime with big ambitions
1const { spawnSync } = require('child_process');
2const path = require('path');
3
4function fail(message) {
5 throw new Error(message);
6}
7
8function runInPty() {
9 const helper = path.join(__dirname, 'fixtures', 'process_stdin_setencoding_tty_child.cjs');
10 const script = `
11import os, select, signal, sys, time
12
13exec_path, helper = sys.argv[1], sys.argv[2]
14pid, master = os.forkpty()
15
16if pid == 0:
17 os.execv(exec_path, [exec_path, helper])
18
19buf = bytearray()
20sent = False
21exit_code = None
22deadline = time.time() + 7.0
23
24while time.time() < deadline:
25 done, status = os.waitpid(pid, os.WNOHANG)
26 if done == pid:
27 exit_code = os.waitstatus_to_exitcode(status)
28 break
29
30 r, _, _ = select.select([master], [], [], 0.1)
31 if master not in r:
32 continue
33
34 try:
35 chunk = os.read(master, 4096)
36 except OSError:
37 break
38
39 if not chunk:
40 break
41
42 buf.extend(chunk)
43 if (not sent) and b'READY' in buf:
44 os.write(master, b'A\\xe2\\x82\\xac')
45 sent = True
46
47if exit_code is None:
48 os.kill(pid, signal.SIGKILL)
49 _, status = os.waitpid(pid, 0)
50 exit_code = os.waitstatus_to_exitcode(status)
51
52while True:
53 r, _, _ = select.select([master], [], [], 0.05)
54 if master not in r:
55 break
56 try:
57 chunk = os.read(master, 4096)
58 except OSError:
59 break
60 if not chunk:
61 break
62 buf.extend(chunk)
63
64sys.stdout.buffer.write(bytes(buf))
65sys.exit(exit_code)
66`;
67
68 if (process.platform === 'win32') {
69 console.log('skipping process.stdin setEncoding tty test on win32');
70 process.exit(0);
71 }
72
73 return spawnSync('python3', ['-c', script, process.execPath, helper], {
74 encoding: 'utf8',
75 timeout: 9000,
76 });
77}
78
79const result = runInPty();
80
81if (result.error && result.error.code === 'ENOENT') {
82 console.log('skipping process.stdin setEncoding tty test because `python3` is unavailable');
83 process.exit(0);
84}
85
86if (result.error) throw result.error;
87
88const output = `${result.stdout || ''}${result.stderr || ''}`;
89
90if (result.status !== 0) {
91 fail(`child exited ${result.status}\n${output}`);
92}
93
94if (!output.includes('READY')) {
95 fail(`expected READY banner\n${output}`);
96}
97
98if (!output.includes('DATA "A€"')) {
99 fail(`expected decoded stdin string payload\n${output}`);
100}
101
102console.log('process.stdin setEncoding decodes tty data');