mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 18:34:21 -10:00
The tree by what each part is, behind the top-level Makefile: - shims/ -> hosts/ (the browser, kernel, native and Wayland hosts) - web/ -> page/ (the page's source, build and serve), ports/mesa, ports/xwayland and ports/tint (the ports the page loads), site/ (static sites and the eject page) - tools/gexcc -> toolchain/gexcc, with the sysroot and busybox builds from tools/wine-wasm in toolchain/sysroot and toolchain/busybox, and one toolchain/pins (musl, the LP64 musl, LLVM, busybox) - tools/wine-wasm -> wine/: dist.sh (was wine64-dist.sh), wine.pins (64-bit Wine, and the 32-bit tree its wineserver builds from), libs.pins (the Unix libraries), the 32-bit-only pieces in wine/legacy32 (its own pins and legacy.mk, which wine/Makefile includes) - tools/*.py and tools/*.sh -> scripts/ (the GL generators in scripts/gl) - wine32/src.sh is scripts/fetch-pinned.sh, which takes the trees the old script marked as its own References follow the moves: paths from the tree's root by the map, paths from a script's own directory by where their target went. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_e0aa53aa95eb4b86910519b4d14812a5
91 lines
4.4 KiB
JavaScript
91 lines
4.4 KiB
JavaScript
// runProgram (page/src/run.js) as a preset over the runtime API
|
|
// (run-program.js): an untarred bundle laid into the root with its hard
|
|
// links, symbolic links, modes, extended attributes, file times and a lazy
|
|
// file; the program, by a directory link's name, a child of the kernel's pid 1, on a terminal bridged to
|
|
// an xterm-shaped object; keys typed into it; its exit status; and its last
|
|
// output before the system stops.
|
|
import { runProgram } from '../../page/src/run.js';
|
|
import { setGlobals } from '../../page/src/page-globals.js';
|
|
import { untar } from '../../page/src/tar.js';
|
|
import { unzstd } from '../../page/src/zfetch.js';
|
|
import { bytesOf } from '../../page/runtime/src/internal.js';
|
|
|
|
export const meta = { hosts: ['browser', 'node'], images: ['busybox'], timeout: 180 };
|
|
|
|
export default async function (t) {
|
|
const { say, check, eq, until, timeout } = t;
|
|
const dbg = t.debug();
|
|
const sw = Object.fromEntries(Object.entries(dbg).filter(([k]) => k !== 'arch'));
|
|
globalThis.GEX_PAGE_SEARCH = `?${new URLSearchParams(sw)}`;
|
|
globalThis.GEX_ASSET_BASE = t.baseUrl;
|
|
setGlobals((n) => sw[n] ?? null, { arch: dbg.arch ?? 'aarch64' });
|
|
const tree = untar(await unzstd(await bytesOf(t.work('bb.tar.zst'))));
|
|
const lazyUrl = new URL(t.work('lazy-program.bin'));
|
|
const lazyAt = lazyUrl.protocol === 'file:' ? decodeURIComponent(lazyUrl.pathname) : lazyUrl.pathname;
|
|
|
|
let out = '';
|
|
let keys = null;
|
|
const term = {
|
|
rows: 24, cols: 80,
|
|
write: (s) => { out += typeof s === 'string' ? s : new TextDecoder().decode(s); },
|
|
writeln: (s) => { out += `${s}\n`; },
|
|
onData: (fn) => { keys = fn; return { dispose() { keys = null; } }; },
|
|
onResize: () => ({ dispose() {} }),
|
|
focus() {},
|
|
};
|
|
const script = [
|
|
'rt-probe tty',
|
|
'echo "ppid $PPID"; cat /proc/1/comm',
|
|
'ls -i /bin/sh /bin/ls | sort -k2 | awk \'{print $1}\' | uniq | wc -l | sed "s/^/inodes /"',
|
|
'ls -l /bin/rt-probe | cut -c1-10 | sed "s/^/mode /"',
|
|
'rt-probe xattr /etc/xattr user.rt',
|
|
'date -r /etc/hello +%s | sed "s/^/mtime /"',
|
|
'cat /etc/hello',
|
|
'wc -c < /lazy.bin | sed "s/^/lazy /"',
|
|
'readlink /etc/link',
|
|
'readlink /lbin | sed "s/^/lbin /"',
|
|
'read x; echo "got $x"',
|
|
'echo last line; exit 7',
|
|
].join('\n');
|
|
const t0 = performance.now();
|
|
const run = runProgram(term, {
|
|
filesystem: 'memory',
|
|
elf: tree.files[tree.hard['/bin/sh'] ?? '/bin/sh'],
|
|
// The program by a directory link's name (/bin/bash, /bin -> usr/bin).
|
|
args: ['/lbin/sh', '-c', script],
|
|
files: { ...tree.files, '/etc/hello': 'hello\n' },
|
|
dirs: [...(tree.dirs ?? []), '/empty'],
|
|
modes: tree.modes,
|
|
hard: tree.hard,
|
|
symlinks: { ...(tree.links ?? {}), '/etc/link': '/etc/hello', '/lbin': 'bin' },
|
|
xattrs: tree.xattrs,
|
|
mtimes: { '/etc/hello': 1000000000 },
|
|
lazy: [['/lazy.bin', 3 << 20, lazyAt]],
|
|
env: ['PATH=/bin:/usr/bin', 'HOME=/root'],
|
|
cwd: '/',
|
|
});
|
|
run.catch((e) => { out += `\n[runProgram threw: ${e?.stack ?? e}]`; });
|
|
await timeout(until(() => /\/dev\/pts\//.test(out), 'the terminal', 60000), 70000, 'start')
|
|
.catch((e) => { throw new Error(`${e.message}: ${out.slice(-600)}`); });
|
|
say(`the program runs in ${(performance.now() - t0).toFixed(0)} ms`);
|
|
keys?.('typed\r');
|
|
const r = await timeout(run, 30000, 'the end');
|
|
const lines = out.replace(/\r/g, '');
|
|
say(lines.split('\n').map((l) => ` | ${l}`).join('\n'));
|
|
eq('the program\'s status', r.status, 7);
|
|
check('the program on a terminal', /^\/dev\/pts\/\d+$/m.test(lines), lines.slice(0, 200));
|
|
// (The terminal echoes the typed keys wherever they fall.)
|
|
check('a child of the kernel\'s pid 1', /^ppid 1$/m.test(lines) && /^init$/m.test(lines));
|
|
check('hard links are one inode', /^inodes 1$/m.test(lines));
|
|
check('a file\'s mode', /^mode -rwxr-xr-x$/m.test(lines));
|
|
check('an extended attribute', /^kept$/m.test(lines));
|
|
check('a file time', /^mtime 1000000000$/m.test(lines));
|
|
check('a file of the caller\'s over the bundle\'s', /^hello$/m.test(lines));
|
|
check('a lazy file', new RegExp(`^lazy ${3 << 20}$`, 'm').test(lines));
|
|
check('a symbolic link', /^\/etc\/hello$/m.test(lines));
|
|
check('the program by a directory link\'s name, the link kept', /^lbin bin$/m.test(lines));
|
|
check('keys from the terminal', /^got typed$/m.test(lines));
|
|
check('the last line before the system stops', /^last line$/m.test(lines));
|
|
eq('the system stopped', r.system?.state.phase, 'stopped');
|
|
}
|