Skip to content

Commit 9b90c3d

Browse files
committed
work in progress on dash-wasm
1 parent 04beaba commit 9b90c3d

File tree

11 files changed

+72
-35
lines changed

11 files changed

+72
-35
lines changed

packages/dash/Makefile

+12-1
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,21 @@ ${BUILD_WASM}/.patched: ${BUILD_WASM}/.build
4545
cd ${BUILD_WASM} && cat ${SRC}/patches/03-dash_main.patch | patch -p1
4646
touch ${BUILD_WASM}/.patched
4747

48+
# NOTES:
49+
# - -DJOBS=0 is to completely disable job control, which isn't supported for WASM yet.
50+
# Right now the first place this fails is in savefd(int from, int ofd), where it uses
51+
# a fcntl argument that is simply not implemented in WASI yet. We will probably have
52+
# to rewrite savefd to use a non-wasi fcntl that we implement.
4853
${DIST_WASM}/.built: ${BUILD_WASM}/.patched
4954
rm -rf ${DIST_WASM}
5055
cd ${BUILD_WASM} \
51-
&& CONFIG_SITE=${BUILD_WASM}/config.site CC="zig cc -target wasm32-wasi" CFLAGS="-Oz -I${LIBEDIT}/wasm/include -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS -I${PACKAGES}/posix-wasm/dist/wasm" ./configure --with-libedit --prefix=${DIST_WASM} --host=none \
56+
&& CONFIG_SITE=${BUILD_WASM}/config.site \
57+
CC="zig cc -target wasm32-wasi" \
58+
CFLAGS="-DJOBS=0 -Oz -I${LIBEDIT}/wasm/include -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS -I${PACKAGES}/posix-wasm/dist/wasm" \
59+
./configure \
60+
--with-libedit \
61+
--prefix=${DIST_WASM} \
62+
--host=none \
5263
&& make -j8 \
5364
&& zig ar -crs libdash.a src/*.o src/*/*.o
5465
mkdir -p ${DIST_WASM}/lib

packages/python-wasm/Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@ ${DIST}/python/%.zip: ${PYTHON_WASM}/lib/dist/%.zip
106106
cp $< $@
107107

108108

109-
${DIST}/python/termcap: ${PYTHON_WASM}/lib/dist/termcap
109+
${DIST}/termcap: ${PYTHON_WASM}/lib/dist/termcap
110110
# Copy over the termcap file (termcap is also in python.zip, but it's useful to have outside for debug mode).
111-
cp ${PYTHON_WASM}/lib/dist/termcap ${DIST}/python/termcap
111+
cp ${PYTHON_WASM}/lib/dist/termcap ${DIST}/termcap
112112

113113
.PHONY: python
114-
python: ${DIST}/python/python.wasm ${DATAFILES} ${PYTHON_PACKAGES} ${DIST}/python/termcap
114+
python: ${DIST}/python/python.wasm ${DATAFILES} ${PYTHON_PACKAGES} ${DIST}/termcap
115115

116116
# ${DIST}/python/py/%.tar.xz: ${PACKAGES}/py-%/dist/wasm/%.tar.xz
117117
# mkdir -p ${DIST}/python/py
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
const std = @import("std");
22
const unistd = @cImport(@cInclude("unistd.h"));
33

4-
extern fn dash_main(argc: c_int, argv: [*]([*:0]u8)) c_int;
4+
extern fn dash_main(argc: c_int, argv: [*c][*c]u8) c_int;
55

6-
pub fn init(argc: i32, argv: [*][*:0]u8) !void {
6+
pub fn terminal(argc: i32, argv: [*c][*c]u8) !i32 {
77
std.debug.print("calling dash... {d}, {s}\n", .{ argc, argv[0] });
88
var ret = dash_main(argc, argv);
99
std.debug.print("returned with ret={d}\n", .{ret});
10+
return ret;
1011
}

packages/python-wasm/src/dash/index.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ import type { FileSystemSpec } from "wasi-js";
44

55
export let wasm: WasmInstance | undefined = undefined;
66

7+
export async function terminal(
8+
argv: string[] = ["/bin/dash"]
9+
): Promise<number> {
10+
if (wasm == null) throw Error("call init - wasm must be initialized");
11+
return await wasm.terminal(argv);
12+
}
13+
714
type WASMImportFunction = (
815
wasmSource: string,
916
options: Options,
@@ -35,12 +42,4 @@ export async function _init({
3542
// critical to do this first, because otherwise process.cwd() gets
3643
// set to '/' (the default in WASM) when any posix call happens.
3744
await wasm.callWithString("chdir", process.cwd());
38-
39-
// This calls Py_Initialize and gets the Python interpreter initialized.
40-
await wasm.callWithString("dash_init", ["/bin/dash"]);
41-
42-
// Wait until the standard libary zip filesystem is loaded, if necessary,
43-
// since user may want to immediately run arbitrary code right when
44-
// this function returns.
45-
await wasm.waitUntilFsLoaded();
4645
}

packages/python-wasm/src/dash/interface.zig

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ export fn keepalive() void {
99

1010
extern fn wasmSetException() void;
1111

12-
export fn dash_init(argc: i32, argv: [*][*:0]u8) i32 {
13-
dash.init(argc, argv) catch |err| {
12+
export fn terminal(argc: i32, argv: [*c][*c]u8) i32 {
13+
return dash.terminal(argc, argv) catch |err| {
1414
wasmSetException();
15-
std.debug.print("dash error: '{}'\nwhen initializing dash runtime", .{err});
15+
std.debug.print("python error: '{}'\nwhen starting terminal", .{err});
1616
return 1;
1717
};
18-
return 0;
1918
}
2019

20+
2121
export fn c_malloc(n: usize) ?*anyopaque {
2222
return std.c.malloc(n);
2323
}

packages/python-wasm/src/dash/node.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import wasmImport from "../wasm/import-node";
22
import wasmImportNoWorker from "../wasm/worker/node";
3-
import { _init, wasm } from "./index";
3+
import { _init, wasm, terminal as _terminal } from "./index";
44
import { join } from "path";
5-
export { wasm };
65

76
const DASH_WASM = "dash.wasm";
87

@@ -20,8 +19,10 @@ export async function init({
2019
const env = {
2120
...process.env,
2221
TERM,
23-
TERMCAP: join(path, "termcap"),
22+
TERMCAP: join(path, "..", "termcap"),
23+
PS1: "dash$ ",
2424
};
25+
//PS1: '$(pwd | sed "s|^$HOME|~|")$ '
2526

2627
await _init({
2728
programName: process.env.PROGRAM_NAME ?? "/usr/bin/dash-wasm", // real name or made up name
@@ -31,3 +32,16 @@ export async function init({
3132
env,
3233
});
3334
}
35+
36+
async function terminal({
37+
argv = [process.env.PROGRAM_NAME ?? "/bin/dash", "-E"],
38+
debug = false,
39+
}: {
40+
argv?: string[];
41+
debug?: boolean;
42+
} = {}): Promise<number> {
43+
await init({ debug });
44+
return await _terminal(argv);
45+
}
46+
47+
export { terminal, wasm };

packages/python-wasm/src/python/node.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function init({
7272
env = {
7373
...process.env,
7474
TERM,
75-
TERMCAP: join(path, "termcap"),
75+
TERMCAP: join(path, "..", "termcap"),
7676
};
7777
}
7878

packages/python-wasm/src/wasm/posix/other.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { notImplemented } from "./util";
2+
//import debug from "debug";
3+
//const log = debug("posix:other");
24

35
export default function other({ callFunction, posix, recv, send }) {
46
function sendStatvfs(bufPtr, x) {
@@ -118,13 +120,6 @@ export default function other({ callFunction, posix, recv, send }) {
118120
notImplemented("tcflush");
119121
},
120122

121-
setjmp: () => {
122-
notImplemented("setjmp");
123-
},
124-
longjmp: () => {
125-
notImplemented("longjmp");
126-
},
127-
128123
// struct passwd *getpwnam(const char *login);
129124
getpwnam: () => {
130125
console.log("STUB: getpwnam");

packages/python-wasm/src/wasm/posix/stdlib.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import { notImplemented } from "./util";
2+
import debug from "debug";
3+
const log_jmp = debug("posix:jmp");
24

35
export default function stdlib({ child_process, os, recv, send, fs }) {
46
return {
7+
setjmp: () => {
8+
// Return 0 so it doesn't do the failure care of the setjmp.
9+
log_jmp("STUB: setjmp - no op");
10+
return 0;
11+
},
12+
513
// void longjmp(jmp_buf env, int val);
6-
longjmp() {
7-
notImplemented("longjmp");
14+
longjmp: () => {
15+
log_jmp("STUB: longjmp - no op");
16+
return 0;
817
},
918

19+
1020
// int getloadavg(double loadavg[], int nelem);
1121
getloadavg: (loadavgDoubleArrayPtr: number, nelem: number): number => {
1222
const { loadavg } = os;

packages/python-wasm/src/wasm/worker/instance.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,21 @@ export default class WasmInstance extends EventEmitter {
103103
}
104104
} else {
105105
// TODO: solve problem in more generality, obviously!
106-
// Convert array of strings to char**
106+
// Convert array of strings to char** of null terminated
107+
// strings, with a null char* at the end as well (common for clib functions)
107108
const ptrs: number[] = [];
108109
for (const s of str) {
109110
ptrs.push(this.send.string(s));
110111
}
111112
const len = ptrs.length;
112-
const ptr = this.exports.c_malloc(len * 4); // sizeof(char*) = 4 in WASM.
113-
const array = new Int32Array(this.memory.buffer, ptr, len);
113+
const ptr = this.exports.c_malloc((len+1) * 4); // sizeof(char*) = 4 in WASM.
114+
const array = new Int32Array(this.memory.buffer, ptr, len+1);
114115
let i = 0;
115116
for (const p of ptrs) {
116117
array[i] = p;
117118
i += 1;
118119
}
120+
array[len] = 0; // final null pointer.
119121
try {
120122
// @ts-ignore
121123
r = f(len, ptr, ...args);

packages/wasi-js/src/wasi.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,12 @@ export default class WASI {
779779
// this.stdinBuffer?.length
780780
// } ${this.stdinBuffer?.toString()}`
781781
// );
782-
//console.log("fd_read", { fd, stats });
782+
// console.log("fd_read", {
783+
// fd,
784+
// stats,
785+
// IS_STDIN,
786+
// getStdin: this.getStdin != null,
787+
// });
783788
outer: for (const iov of getiovs(iovs, iovsLen)) {
784789
let r = 0;
785790
while (r < iov.byteLength) {

0 commit comments

Comments
 (0)