@ai-ecoverse/slicc-kernel 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -4
- package/dist/kernel-worker.js +496 -75
- package/dist/kernel-worker.js.map +4 -4
- package/dist/process-worker.js +4403 -664
- package/dist/process-worker.js.map +4 -4
- package/package.json +7 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -1206,12 +1206,12 @@ var Budget = class {
|
|
|
1206
1206
|
while (this.free < n) {
|
|
1207
1207
|
signal.throwIfAborted();
|
|
1208
1208
|
await new Promise((resolve) => {
|
|
1209
|
-
const
|
|
1210
|
-
signal.removeEventListener("abort",
|
|
1209
|
+
const done4 = () => {
|
|
1210
|
+
signal.removeEventListener("abort", done4);
|
|
1211
1211
|
resolve();
|
|
1212
1212
|
};
|
|
1213
|
-
this.waiters.push(
|
|
1214
|
-
signal.addEventListener("abort",
|
|
1213
|
+
this.waiters.push(done4);
|
|
1214
|
+
signal.addEventListener("abort", done4, { once: true });
|
|
1215
1215
|
});
|
|
1216
1216
|
}
|
|
1217
1217
|
this.free -= n;
|
|
@@ -1422,11 +1422,11 @@ var RealmProxy = class {
|
|
|
1422
1422
|
this.slots.release(1);
|
|
1423
1423
|
break;
|
|
1424
1424
|
}
|
|
1425
|
-
const
|
|
1425
|
+
const done4 = this.serve(conn).finally(() => {
|
|
1426
1426
|
this.slots.release(1);
|
|
1427
|
-
served.delete(
|
|
1427
|
+
served.delete(done4);
|
|
1428
1428
|
});
|
|
1429
|
-
served.add(
|
|
1429
|
+
served.add(done4);
|
|
1430
1430
|
}
|
|
1431
1431
|
} catch {
|
|
1432
1432
|
}
|
|
@@ -2450,44 +2450,83 @@ function envOf(pkg, raw) {
|
|
|
2450
2450
|
const env = {};
|
|
2451
2451
|
if (!raw || typeof raw !== "object") return env;
|
|
2452
2452
|
for (const [key, value] of Object.entries(raw)) {
|
|
2453
|
-
if (ENV_KEY.test(key)
|
|
2453
|
+
if (!ENV_KEY.test(key)) continue;
|
|
2454
|
+
if (typeof value === "string") env[key] = value.replace(PACKAGE, pkg);
|
|
2455
|
+
else if (value === null) env[key] = null;
|
|
2454
2456
|
}
|
|
2455
2457
|
return env;
|
|
2456
2458
|
}
|
|
2459
|
+
function envFields(merged) {
|
|
2460
|
+
const env = {};
|
|
2461
|
+
const unset = [];
|
|
2462
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
2463
|
+
if (value === null) unset.push(key);
|
|
2464
|
+
else env[key] = value;
|
|
2465
|
+
}
|
|
2466
|
+
return {
|
|
2467
|
+
...Object.keys(env).length > 0 ? { env } : {},
|
|
2468
|
+
...unset.length > 0 ? { unset } : {}
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
2457
2471
|
function argsOf(pkg, raw) {
|
|
2458
2472
|
if (!Array.isArray(raw) || raw.length === 0) return void 0;
|
|
2459
2473
|
if (!raw.every((arg) => typeof arg === "string")) return void 0;
|
|
2460
2474
|
return raw.map((arg) => arg.replace(PACKAGE, pkg));
|
|
2461
2475
|
}
|
|
2476
|
+
function abiOf(raw, fallback) {
|
|
2477
|
+
const abi = raw ?? fallback;
|
|
2478
|
+
return abi === "emscripten" || abi === "wasi" ? abi : void 0;
|
|
2479
|
+
}
|
|
2480
|
+
function commandOf(pkg, name2, raw, packageAbi, shared) {
|
|
2481
|
+
const withEnv = envFields({ ...shared, ...envOf(pkg, raw.env) });
|
|
2482
|
+
const script = inside(pkg, raw.script);
|
|
2483
|
+
if (script) {
|
|
2484
|
+
return { name: name2, abi: packageAbi, glue: script, wasm: script, argv0: name2, script, ...withEnv };
|
|
2485
|
+
}
|
|
2486
|
+
const abi = abiOf(raw.abi, packageAbi);
|
|
2487
|
+
const wasm = inside(pkg, raw.wasm);
|
|
2488
|
+
const glue = abi === "wasi" ? wasm : inside(pkg, raw.glue);
|
|
2489
|
+
if (!abi || !glue || !wasm) return void 0;
|
|
2490
|
+
const argv0 = typeof raw.argv0 === "string" && raw.argv0 ? raw.argv0 : name2;
|
|
2491
|
+
const args = argsOf(pkg, raw.args);
|
|
2492
|
+
const imports = abi === "wasi" ? inside(pkg, raw.imports) : void 0;
|
|
2493
|
+
return {
|
|
2494
|
+
name: name2,
|
|
2495
|
+
abi,
|
|
2496
|
+
glue,
|
|
2497
|
+
wasm,
|
|
2498
|
+
argv0,
|
|
2499
|
+
...args ? { args } : {},
|
|
2500
|
+
...withEnv,
|
|
2501
|
+
...imports ? { imports } : {}
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2462
2504
|
function commandsOf(pkg, manifest) {
|
|
2463
2505
|
const slicc = manifest.slicc;
|
|
2464
|
-
if (!slicc || typeof slicc !== "object"
|
|
2465
|
-
|
|
2506
|
+
if (!slicc || typeof slicc !== "object") return [];
|
|
2507
|
+
const packageAbi = abiOf(slicc.abi, "emscripten");
|
|
2466
2508
|
const entries = slicc.commands;
|
|
2467
|
-
if (!entries || typeof entries !== "object") return [];
|
|
2509
|
+
if (!packageAbi || !entries || typeof entries !== "object") return [];
|
|
2468
2510
|
const shared = envOf(pkg, slicc.env);
|
|
2469
2511
|
const out = [];
|
|
2470
2512
|
for (const [name2, raw] of Object.entries(entries)) {
|
|
2471
2513
|
if (!NAME.test(name2) || name2 === "." || name2 === ".." || !raw || typeof raw !== "object") {
|
|
2472
2514
|
continue;
|
|
2473
2515
|
}
|
|
2474
|
-
const
|
|
2475
|
-
|
|
2476
|
-
if ((raw.abi ?? "emscripten") !== "emscripten" || !glue || !wasm) continue;
|
|
2477
|
-
const argv0 = typeof raw.argv0 === "string" && raw.argv0 ? raw.argv0 : name2;
|
|
2478
|
-
const args = argsOf(pkg, raw.args);
|
|
2479
|
-
const env = { ...shared, ...envOf(pkg, raw.env) };
|
|
2480
|
-
out.push({
|
|
2481
|
-
name: name2,
|
|
2482
|
-
glue,
|
|
2483
|
-
wasm,
|
|
2484
|
-
argv0,
|
|
2485
|
-
...args ? { args } : {},
|
|
2486
|
-
...Object.keys(env).length > 0 ? { env } : {}
|
|
2487
|
-
});
|
|
2516
|
+
const command = commandOf(pkg, name2, raw, packageAbi, shared);
|
|
2517
|
+
if (command) out.push(command);
|
|
2488
2518
|
}
|
|
2489
2519
|
return out;
|
|
2490
2520
|
}
|
|
2521
|
+
async function withPackagePaths(fs, pkg, command) {
|
|
2522
|
+
if (!command.env) return command;
|
|
2523
|
+
const env = {};
|
|
2524
|
+
for (const [key, value] of Object.entries(command.env)) {
|
|
2525
|
+
const path = !value.startsWith("/") && value.includes("/") && inside(pkg, value);
|
|
2526
|
+
env[key] = path && await fs.exists(path) ? path : value;
|
|
2527
|
+
}
|
|
2528
|
+
return { ...command, env };
|
|
2529
|
+
}
|
|
2491
2530
|
async function packages(fs, modules) {
|
|
2492
2531
|
const names = await fs.readdir(modules).catch(() => []);
|
|
2493
2532
|
const dirs = [];
|
|
@@ -2513,7 +2552,8 @@ async function scanCommands(fs, modules) {
|
|
|
2513
2552
|
continue;
|
|
2514
2553
|
}
|
|
2515
2554
|
for (const command of commandsOf(pkg, manifest)) {
|
|
2516
|
-
if (!found.has(command.name))
|
|
2555
|
+
if (!found.has(command.name))
|
|
2556
|
+
found.set(command.name, await withPackagePaths(fs, pkg, command));
|
|
2517
2557
|
}
|
|
2518
2558
|
}
|
|
2519
2559
|
if (!found.has("sh") && found.has("bash")) {
|
|
@@ -2750,8 +2790,8 @@ var ChildTable = class {
|
|
|
2750
2790
|
for (; ; ) {
|
|
2751
2791
|
const candidates = this.candidates(pid, flags);
|
|
2752
2792
|
if (candidates.length === 0) throw new KernelError("ECHILD");
|
|
2753
|
-
const
|
|
2754
|
-
if (
|
|
2793
|
+
const done4 = candidates.find(([, child]) => child.code !== void 0);
|
|
2794
|
+
if (done4) return this.reap(done4[0], done4[1].code);
|
|
2755
2795
|
const changed = this.stateReport(candidates, flags);
|
|
2756
2796
|
if (changed) return changed;
|
|
2757
2797
|
if (nohang) return [0, 0];
|
|
@@ -3061,6 +3101,167 @@ function attachSyncSabResponder(port, sab, token, opts) {
|
|
|
3061
3101
|
};
|
|
3062
3102
|
}
|
|
3063
3103
|
|
|
3104
|
+
// src/kernel/host-ops.ts
|
|
3105
|
+
var HOST_OPS = [
|
|
3106
|
+
"lock",
|
|
3107
|
+
"unlock",
|
|
3108
|
+
"async-submit",
|
|
3109
|
+
"async-wait",
|
|
3110
|
+
"async-take",
|
|
3111
|
+
"async-resolve",
|
|
3112
|
+
"async-hold",
|
|
3113
|
+
"async-cancel",
|
|
3114
|
+
"async-close"
|
|
3115
|
+
];
|
|
3116
|
+
var json2 = (value) => ({ ok: true, kind: "json", json: value });
|
|
3117
|
+
var done2 = { ok: true, kind: "void" };
|
|
3118
|
+
var LockTable = class {
|
|
3119
|
+
held = /* @__PURE__ */ new Map();
|
|
3120
|
+
lock(pid, path, exclusive, fd) {
|
|
3121
|
+
const holders = this.held.get(path) ?? /* @__PURE__ */ new Map();
|
|
3122
|
+
for (const [other, h] of holders) if (other !== pid && (exclusive || h.exclusive)) return false;
|
|
3123
|
+
const mine = holders.get(pid) ?? { exclusive, fds: /* @__PURE__ */ new Set() };
|
|
3124
|
+
mine.exclusive = exclusive;
|
|
3125
|
+
mine.fds.add(fd);
|
|
3126
|
+
holders.set(pid, mine);
|
|
3127
|
+
this.held.set(path, holders);
|
|
3128
|
+
return true;
|
|
3129
|
+
}
|
|
3130
|
+
unlock(pid, path) {
|
|
3131
|
+
const holders = this.held.get(path);
|
|
3132
|
+
holders?.delete(pid);
|
|
3133
|
+
if (holders?.size === 0) this.held.delete(path);
|
|
3134
|
+
}
|
|
3135
|
+
closed(pid, fd) {
|
|
3136
|
+
for (const [path, holders] of [...this.held]) {
|
|
3137
|
+
const mine = holders.get(pid);
|
|
3138
|
+
if (mine?.fds.delete(fd) && mine.fds.size === 0) this.unlock(pid, path);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
release(pid) {
|
|
3142
|
+
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
3143
|
+
}
|
|
3144
|
+
};
|
|
3145
|
+
var AsyncOps = class {
|
|
3146
|
+
next = 1;
|
|
3147
|
+
results = /* @__PURE__ */ new Map();
|
|
3148
|
+
ready = [];
|
|
3149
|
+
waiters = /* @__PURE__ */ new Set();
|
|
3150
|
+
closed = false;
|
|
3151
|
+
run;
|
|
3152
|
+
constructor(run2) {
|
|
3153
|
+
this.run = run2;
|
|
3154
|
+
}
|
|
3155
|
+
submit(req) {
|
|
3156
|
+
const id = this.hold();
|
|
3157
|
+
this.run(req).then(
|
|
3158
|
+
(result) => this.complete(id, result),
|
|
3159
|
+
(err) => this.complete(id, { ok: false, errno: "EIO", message: String(err) })
|
|
3160
|
+
);
|
|
3161
|
+
return id;
|
|
3162
|
+
}
|
|
3163
|
+
resolve(value) {
|
|
3164
|
+
const id = this.hold();
|
|
3165
|
+
this.complete(id, json2(value));
|
|
3166
|
+
return id;
|
|
3167
|
+
}
|
|
3168
|
+
hold() {
|
|
3169
|
+
const id = this.next++;
|
|
3170
|
+
this.results.set(id, void 0);
|
|
3171
|
+
return id;
|
|
3172
|
+
}
|
|
3173
|
+
take(id) {
|
|
3174
|
+
if (!this.results.has(id)) throw new KernelError("EINVAL");
|
|
3175
|
+
const result = this.results.get(id);
|
|
3176
|
+
if (!result) throw new KernelError("EAGAIN");
|
|
3177
|
+
this.cancel(id);
|
|
3178
|
+
return result;
|
|
3179
|
+
}
|
|
3180
|
+
cancel(id) {
|
|
3181
|
+
this.results.delete(id);
|
|
3182
|
+
const at = this.ready.indexOf(id);
|
|
3183
|
+
if (at >= 0) this.ready.splice(at, 1);
|
|
3184
|
+
}
|
|
3185
|
+
async wait(timeoutMs, signal) {
|
|
3186
|
+
for (; ; ) {
|
|
3187
|
+
if (this.closed) return -1;
|
|
3188
|
+
const id = this.ready.shift();
|
|
3189
|
+
if (id !== void 0) return id;
|
|
3190
|
+
if (timeoutMs !== void 0 && timeoutMs <= 0) return 0;
|
|
3191
|
+
const woke = await this.sleep(timeoutMs, signal);
|
|
3192
|
+
if (!woke) return 0;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
close() {
|
|
3196
|
+
this.closed = true;
|
|
3197
|
+
this.wake();
|
|
3198
|
+
}
|
|
3199
|
+
sleep(timeoutMs, signal) {
|
|
3200
|
+
return new Promise((resolve, reject) => {
|
|
3201
|
+
let timer;
|
|
3202
|
+
const cleanup = () => {
|
|
3203
|
+
clearTimeout(timer);
|
|
3204
|
+
this.waiters.delete(wake);
|
|
3205
|
+
signal.removeEventListener("abort", abort);
|
|
3206
|
+
};
|
|
3207
|
+
const wake = () => {
|
|
3208
|
+
cleanup();
|
|
3209
|
+
resolve(true);
|
|
3210
|
+
};
|
|
3211
|
+
const abort = () => {
|
|
3212
|
+
cleanup();
|
|
3213
|
+
reject(new KernelError("EINTR"));
|
|
3214
|
+
};
|
|
3215
|
+
this.waiters.add(wake);
|
|
3216
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
3217
|
+
if (timeoutMs !== void 0) {
|
|
3218
|
+
timer = setTimeout(() => {
|
|
3219
|
+
cleanup();
|
|
3220
|
+
resolve(false);
|
|
3221
|
+
}, timeoutMs);
|
|
3222
|
+
}
|
|
3223
|
+
});
|
|
3224
|
+
}
|
|
3225
|
+
complete(id, result) {
|
|
3226
|
+
if (!this.results.has(id)) return;
|
|
3227
|
+
this.results.set(id, result);
|
|
3228
|
+
this.ready.push(id);
|
|
3229
|
+
this.wake();
|
|
3230
|
+
}
|
|
3231
|
+
wake() {
|
|
3232
|
+
for (const wake of [...this.waiters]) wake();
|
|
3233
|
+
}
|
|
3234
|
+
};
|
|
3235
|
+
async function hostSyscall(req, ctx) {
|
|
3236
|
+
switch (req.op) {
|
|
3237
|
+
case "lock":
|
|
3238
|
+
if (!ctx.locks) throw new KernelError("ENOSYS");
|
|
3239
|
+
if (!ctx.locks.lock(ctx.pid, req.path, req.exclusive, req.fd))
|
|
3240
|
+
throw new KernelError("EAGAIN");
|
|
3241
|
+
return done2;
|
|
3242
|
+
case "unlock":
|
|
3243
|
+
ctx.locks?.unlock(ctx.pid, req.path);
|
|
3244
|
+
return done2;
|
|
3245
|
+
case "async-submit":
|
|
3246
|
+
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
3247
|
+
return json2(ctx.ops.submit(req.req));
|
|
3248
|
+
case "async-wait":
|
|
3249
|
+
return json2(await ctx.ops.wait(req.timeoutMs, ctx.blocking()));
|
|
3250
|
+
case "async-take":
|
|
3251
|
+
return ctx.ops.take(req.id);
|
|
3252
|
+
case "async-resolve":
|
|
3253
|
+
return json2(ctx.ops.resolve(req.value));
|
|
3254
|
+
case "async-hold":
|
|
3255
|
+
return json2(ctx.ops.hold());
|
|
3256
|
+
case "async-cancel":
|
|
3257
|
+
ctx.ops.cancel(req.id);
|
|
3258
|
+
return done2;
|
|
3259
|
+
case "async-close":
|
|
3260
|
+
ctx.ops.close();
|
|
3261
|
+
return done2;
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3064
3265
|
// src/kernel/net/http-syscalls.ts
|
|
3065
3266
|
var HTTP_OPS = ["net-request", "net-read", "net-close"];
|
|
3066
3267
|
var EMPTY = new Uint8Array(0);
|
|
@@ -3571,41 +3772,41 @@ function terminalOf(ctx, fd) {
|
|
|
3571
3772
|
if (!tty) throw new KernelError("ENOTTY");
|
|
3572
3773
|
return tty;
|
|
3573
3774
|
}
|
|
3574
|
-
var
|
|
3575
|
-
var
|
|
3775
|
+
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
3776
|
+
var done3 = { ok: true, kind: "void" };
|
|
3576
3777
|
function ptySyscall(req, ctx) {
|
|
3577
3778
|
switch (req.op) {
|
|
3578
3779
|
case "pty-open": {
|
|
3579
3780
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
3580
|
-
return
|
|
3781
|
+
return json3(ctx.fds.install(ctx.ptys.open().master, 3));
|
|
3581
3782
|
}
|
|
3582
3783
|
case "pty-slave-open": {
|
|
3583
3784
|
if (!ctx.ptys) throw new KernelError("ENOENT");
|
|
3584
3785
|
const pair = ctx.ptys.get(req.n);
|
|
3585
3786
|
const fd = ctx.fds.install(pair.openSlave(), 3);
|
|
3586
3787
|
if (!req.noctty) ctx.jobs?.acquireTerminal(ctx.pid, pair.slave);
|
|
3587
|
-
return
|
|
3788
|
+
return json3(fd);
|
|
3588
3789
|
}
|
|
3589
3790
|
case "pty-number":
|
|
3590
|
-
return
|
|
3791
|
+
return json3(masterOf(ctx, req.fd).index);
|
|
3591
3792
|
case "pty-lock":
|
|
3592
3793
|
masterOf(ctx, req.fd).locked = req.lock;
|
|
3593
|
-
return
|
|
3794
|
+
return done3;
|
|
3594
3795
|
case "pty-ctty": {
|
|
3595
3796
|
const tty = terminalOf(ctx, req.fd);
|
|
3596
3797
|
const leader = ctx.jobs?.getsid(ctx.pid, 0) === ctx.pid;
|
|
3597
|
-
if (leader && ctx.jobs?.controllingTerminal(ctx.pid) === tty) return
|
|
3798
|
+
if (leader && ctx.jobs?.controllingTerminal(ctx.pid) === tty) return done3;
|
|
3598
3799
|
if (!ctx.jobs?.acquireTerminal(ctx.pid, tty)) throw new KernelError("EPERM");
|
|
3599
|
-
return
|
|
3800
|
+
return done3;
|
|
3600
3801
|
}
|
|
3601
3802
|
case "pty-list":
|
|
3602
|
-
return
|
|
3803
|
+
return json3(ctx.ptys?.numbers() ?? []);
|
|
3603
3804
|
case "pty-packet":
|
|
3604
3805
|
masterOf(ctx, req.fd).packet = req.on;
|
|
3605
|
-
return
|
|
3806
|
+
return done3;
|
|
3606
3807
|
case "pty-winsz-set":
|
|
3607
3808
|
terminalOf(ctx, req.fd).resize(req.cols, req.rows);
|
|
3608
|
-
return
|
|
3809
|
+
return done3;
|
|
3609
3810
|
}
|
|
3610
3811
|
}
|
|
3611
3812
|
|
|
@@ -3990,7 +4191,7 @@ function socketAt(fds, fd) {
|
|
|
3990
4191
|
if (!(file instanceof KernelSocket)) throw new KernelError("ENOTSOCK");
|
|
3991
4192
|
return file;
|
|
3992
4193
|
}
|
|
3993
|
-
var ok = (
|
|
4194
|
+
var ok = (json4) => json4 === void 0 ? { ok: true, kind: "void" } : { ok: true, kind: "json", json: json4 };
|
|
3994
4195
|
async function socketSyscall(req, proc) {
|
|
3995
4196
|
const { fds, net } = proc;
|
|
3996
4197
|
switch (req.op) {
|
|
@@ -4316,6 +4517,9 @@ function isHttpSyscall(req) {
|
|
|
4316
4517
|
function isSocketSyscall(req) {
|
|
4317
4518
|
return req.op.startsWith("sock-");
|
|
4318
4519
|
}
|
|
4520
|
+
function isHostSyscall(req) {
|
|
4521
|
+
return HOST_OPS.includes(req.op);
|
|
4522
|
+
}
|
|
4319
4523
|
function isPtySyscall(req) {
|
|
4320
4524
|
return req.op.startsWith("pty-");
|
|
4321
4525
|
}
|
|
@@ -4353,6 +4557,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
4353
4557
|
"fd-cloexec",
|
|
4354
4558
|
"fd-list",
|
|
4355
4559
|
"proc-alarm",
|
|
4560
|
+
"dl-log",
|
|
4356
4561
|
"fd-renumber",
|
|
4357
4562
|
"fd-promote",
|
|
4358
4563
|
"fd-open-tty",
|
|
@@ -4376,7 +4581,8 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
4376
4581
|
"sig-pause",
|
|
4377
4582
|
...SOCKET_OPS,
|
|
4378
4583
|
...HTTP_OPS,
|
|
4379
|
-
...PTY_OPS
|
|
4584
|
+
...PTY_OPS,
|
|
4585
|
+
...HOST_OPS
|
|
4380
4586
|
]);
|
|
4381
4587
|
function isWasmSyscall(req) {
|
|
4382
4588
|
const op = req.op;
|
|
@@ -4424,6 +4630,9 @@ var WasmProcess = class {
|
|
|
4424
4630
|
const action = defaultAction(sig);
|
|
4425
4631
|
return action === "stop" ? this.stop(sig) : action;
|
|
4426
4632
|
}
|
|
4633
|
+
if (((this.options.pendingBits?.() ?? 0) & bit) !== 0 && defaultAction(sig) === "terminate") {
|
|
4634
|
+
return "terminate";
|
|
4635
|
+
}
|
|
4427
4636
|
this.options.onPending?.(sig);
|
|
4428
4637
|
const blocked = this.interrupt;
|
|
4429
4638
|
this.interrupt = new AbortController();
|
|
@@ -4468,6 +4677,15 @@ var WasmProcess = class {
|
|
|
4468
4677
|
if (isJobSyscall(req)) return this.jobSyscall(req);
|
|
4469
4678
|
if (isSocketSyscall(req)) return await this.socketSyscall(req);
|
|
4470
4679
|
if (isHttpSyscall(req)) return await this.httpSyscall(req);
|
|
4680
|
+
if (isHostSyscall(req)) {
|
|
4681
|
+
return await hostSyscall(req, {
|
|
4682
|
+
pid: this.pid,
|
|
4683
|
+
locks: this.options.locks,
|
|
4684
|
+
ops: this.asyncOps,
|
|
4685
|
+
blocking: () => this.blockingSignal(),
|
|
4686
|
+
valid: (inner) => isWasmSyscall(inner) && !isHostSyscall(inner)
|
|
4687
|
+
});
|
|
4688
|
+
}
|
|
4471
4689
|
if (isPtySyscall(req)) {
|
|
4472
4690
|
const { ptys, jobs } = this.options;
|
|
4473
4691
|
return ptySyscall(req, { pid: this.pid, fds: this.fds, ptys, jobs });
|
|
@@ -4531,6 +4749,7 @@ var WasmProcess = class {
|
|
|
4531
4749
|
case "fd-write":
|
|
4532
4750
|
return { ok: true, kind: "json", json: await this.write(req.fd, req.body, req.nonblock) };
|
|
4533
4751
|
case "fd-close":
|
|
4752
|
+
this.options.locks?.closed(this.pid, req.fd);
|
|
4534
4753
|
await Promise.resolve(this.fds.close(req.fd));
|
|
4535
4754
|
return { ok: true, kind: "void" };
|
|
4536
4755
|
case "fd-pipe": {
|
|
@@ -4802,6 +5021,9 @@ var WasmProcess = class {
|
|
|
4802
5021
|
case "proc-alarm":
|
|
4803
5022
|
this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
|
|
4804
5023
|
return { ok: true, kind: "void" };
|
|
5024
|
+
case "dl-log":
|
|
5025
|
+
if (req.append) this.dlLog.push(req.append);
|
|
5026
|
+
return { ok: true, kind: "json", json: this.dlLog.slice(req.from) };
|
|
4805
5027
|
case "sig-mask":
|
|
4806
5028
|
this.caught = req.caught;
|
|
4807
5029
|
this.ignored = req.ignored;
|
|
@@ -4819,6 +5041,8 @@ var WasmProcess = class {
|
|
|
4819
5041
|
});
|
|
4820
5042
|
}
|
|
4821
5043
|
alarm;
|
|
5044
|
+
dlLog = [];
|
|
5045
|
+
asyncOps = new AsyncOps((req) => this.syscall(req));
|
|
4822
5046
|
alarmEvery;
|
|
4823
5047
|
setAlarm(sig, first, every, timer) {
|
|
4824
5048
|
if (!isSignal(sig)) throw new KernelError("EINVAL");
|
|
@@ -4847,6 +5071,8 @@ var WasmProcess = class {
|
|
|
4847
5071
|
if (this.exited) return;
|
|
4848
5072
|
this.exited = true;
|
|
4849
5073
|
this.clearAlarm();
|
|
5074
|
+
this.options.locks?.release(this.pid);
|
|
5075
|
+
this.asyncOps.close();
|
|
4850
5076
|
for (const pid of this.children.pids()) this.options.onReap?.(pid);
|
|
4851
5077
|
await this.fds.closeAll();
|
|
4852
5078
|
await this.options.http?.closeAll();
|
|
@@ -4857,6 +5083,10 @@ var WasmProcess = class {
|
|
|
4857
5083
|
var WASM_PROCESS_INIT = "wasm-process-init";
|
|
4858
5084
|
var WASM_PROCESS_EXIT = "wasm-process-exit";
|
|
4859
5085
|
var WASM_PROCESS_ERROR = "wasm-process-error";
|
|
5086
|
+
var WASM_THREAD_SPAWN = "wasm-thread-spawn";
|
|
5087
|
+
var WASM_THREAD_INIT = "wasm-thread-init";
|
|
5088
|
+
var WASM_THREAD_EXIT = "wasm-thread-exit";
|
|
5089
|
+
var WASM_MAX_THREADS = 64;
|
|
4860
5090
|
|
|
4861
5091
|
// src/kernel/host.ts
|
|
4862
5092
|
var CRASHED = 70;
|
|
@@ -4895,11 +5125,13 @@ function spawnWasmProcess(opts) {
|
|
|
4895
5125
|
ptys: opts.ptys,
|
|
4896
5126
|
net: opts.net,
|
|
4897
5127
|
http: opts.http,
|
|
5128
|
+
locks: opts.locks,
|
|
4898
5129
|
onReap: opts.onReap,
|
|
4899
5130
|
onPending: (sig) => void Atomics.or(header2, SAB_I_SIGNALS, sigbit(sig)),
|
|
4900
5131
|
onTimer: (which) => void Atomics.or(header2, SAB_I_TIMERS, 1 << which),
|
|
4901
5132
|
hasPending: () => Atomics.load(header2, SAB_I_SIGNALS) !== 0 || Atomics.load(header2, SAB_I_TIMERS) !== 0,
|
|
4902
|
-
raise: (sig) => signal(sig)
|
|
5133
|
+
raise: (sig) => signal(sig),
|
|
5134
|
+
...opts.program.abi === "wasi" ? { pendingBits: () => Atomics.load(header2, SAB_I_SIGNALS) } : {}
|
|
4903
5135
|
});
|
|
4904
5136
|
const token = mintSyncFsToken({ fs: opts.fs, cwd: opts.cwd });
|
|
4905
5137
|
const worker = opts.createWorker();
|
|
@@ -4910,14 +5142,15 @@ function spawnWasmProcess(opts) {
|
|
|
4910
5142
|
const responder = attachSyncSabResponder(worker, sab, token, { dispatch });
|
|
4911
5143
|
let settle2;
|
|
4912
5144
|
const exited = new Promise((resolve) => settle2 = resolve);
|
|
4913
|
-
let
|
|
5145
|
+
let done4 = false;
|
|
4914
5146
|
let endedBy;
|
|
4915
5147
|
const finish = (code, sig) => {
|
|
4916
|
-
if (
|
|
4917
|
-
|
|
5148
|
+
if (done4) return;
|
|
5149
|
+
done4 = true;
|
|
4918
5150
|
endedBy = sig ?? process.execTermsig;
|
|
4919
5151
|
worker.removeEventListener("message", onMessage);
|
|
4920
5152
|
worker.removeEventListener("error", onError);
|
|
5153
|
+
for (const tid of [...threads.keys()]) endThread(tid);
|
|
4921
5154
|
responder.dispose();
|
|
4922
5155
|
revokeSyncFsToken(token);
|
|
4923
5156
|
worker.terminate();
|
|
@@ -4926,15 +5159,17 @@ function spawnWasmProcess(opts) {
|
|
|
4926
5159
|
() => settle2(code)
|
|
4927
5160
|
);
|
|
4928
5161
|
};
|
|
4929
|
-
const
|
|
4930
|
-
const data = event.data;
|
|
5162
|
+
const handle = (data) => {
|
|
4931
5163
|
if (data?.type === WASM_PROCESS_EXIT) {
|
|
4932
5164
|
finish(typeof data.code === "number" ? data.code : CRASHED);
|
|
4933
5165
|
} else if (data?.type === WASM_PROCESS_ERROR) {
|
|
4934
5166
|
opts.onError?.(String(data.message));
|
|
4935
5167
|
finish(CRASHED);
|
|
5168
|
+
} else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
|
|
5169
|
+
spawnThread(data.thread);
|
|
4936
5170
|
}
|
|
4937
5171
|
};
|
|
5172
|
+
const onMessage = (event) => handle(event.data);
|
|
4938
5173
|
const onError = (event) => {
|
|
4939
5174
|
event.preventDefault();
|
|
4940
5175
|
opts.onError?.(String(event.message ?? "worker error"));
|
|
@@ -4942,6 +5177,49 @@ function spawnWasmProcess(opts) {
|
|
|
4942
5177
|
};
|
|
4943
5178
|
worker.addEventListener("message", onMessage);
|
|
4944
5179
|
worker.addEventListener("error", onError);
|
|
5180
|
+
const threads = /* @__PURE__ */ new Map();
|
|
5181
|
+
const endThread = (tid) => {
|
|
5182
|
+
const end = threads.get(tid);
|
|
5183
|
+
threads.delete(tid);
|
|
5184
|
+
end?.();
|
|
5185
|
+
};
|
|
5186
|
+
const spawnThread = (thread) => {
|
|
5187
|
+
if (done4) return;
|
|
5188
|
+
if (threads.size >= WASM_MAX_THREADS - 1) {
|
|
5189
|
+
opts.onError?.(`more than ${WASM_MAX_THREADS} threads`);
|
|
5190
|
+
finish(CRASHED);
|
|
5191
|
+
return;
|
|
5192
|
+
}
|
|
5193
|
+
const tsab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
5194
|
+
const tw = opts.createWorker();
|
|
5195
|
+
const tresponder = attachSyncSabResponder(tw, tsab, token, { dispatch });
|
|
5196
|
+
const onThreadMessage = (event) => {
|
|
5197
|
+
const data = event.data;
|
|
5198
|
+
if (data?.type === WASM_THREAD_EXIT) endThread(thread.tid);
|
|
5199
|
+
else handle(data);
|
|
5200
|
+
};
|
|
5201
|
+
tw.addEventListener("message", onThreadMessage);
|
|
5202
|
+
tw.addEventListener("error", onError);
|
|
5203
|
+
threads.set(thread.tid, () => {
|
|
5204
|
+
tw.removeEventListener("message", onThreadMessage);
|
|
5205
|
+
tw.removeEventListener("error", onError);
|
|
5206
|
+
tresponder.dispose();
|
|
5207
|
+
tw.terminate();
|
|
5208
|
+
});
|
|
5209
|
+
const tinit = {
|
|
5210
|
+
type: WASM_THREAD_INIT,
|
|
5211
|
+
pid: opts.pid,
|
|
5212
|
+
program: opts.program,
|
|
5213
|
+
argv0: opts.argv0,
|
|
5214
|
+
args: opts.args,
|
|
5215
|
+
env: opts.env,
|
|
5216
|
+
cwd: opts.cwd,
|
|
5217
|
+
sab: tsab,
|
|
5218
|
+
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
5219
|
+
thread
|
|
5220
|
+
};
|
|
5221
|
+
tw.postMessage(tinit);
|
|
5222
|
+
};
|
|
4945
5223
|
const init = {
|
|
4946
5224
|
type: WASM_PROCESS_INIT,
|
|
4947
5225
|
pid: opts.pid,
|
|
@@ -5076,8 +5354,67 @@ var JobTable = class {
|
|
|
5076
5354
|
}
|
|
5077
5355
|
};
|
|
5078
5356
|
|
|
5357
|
+
// src/process/wasi/wasi-module.ts
|
|
5358
|
+
function importedMemory(bytes) {
|
|
5359
|
+
let at = 8;
|
|
5360
|
+
const u32 = () => {
|
|
5361
|
+
let result = 0;
|
|
5362
|
+
let shift = 0;
|
|
5363
|
+
for (; ; ) {
|
|
5364
|
+
const b = bytes[at++];
|
|
5365
|
+
result |= (b & 127) << shift;
|
|
5366
|
+
if (!(b & 128)) return result >>> 0;
|
|
5367
|
+
shift += 7;
|
|
5368
|
+
}
|
|
5369
|
+
};
|
|
5370
|
+
const name2 = () => {
|
|
5371
|
+
const len = u32();
|
|
5372
|
+
const s = new TextDecoder().decode(bytes.subarray(at, at + len));
|
|
5373
|
+
at += len;
|
|
5374
|
+
return s;
|
|
5375
|
+
};
|
|
5376
|
+
const limits = () => {
|
|
5377
|
+
const flags = bytes[at++];
|
|
5378
|
+
const initial = u32();
|
|
5379
|
+
const maximum = flags & 1 ? u32() : void 0;
|
|
5380
|
+
return { initial, maximum, shared: (flags & 2) !== 0 };
|
|
5381
|
+
};
|
|
5382
|
+
while (at < bytes.length) {
|
|
5383
|
+
const id = bytes[at++];
|
|
5384
|
+
const size = u32();
|
|
5385
|
+
const end = at + size;
|
|
5386
|
+
if (id !== 2) {
|
|
5387
|
+
at = end;
|
|
5388
|
+
continue;
|
|
5389
|
+
}
|
|
5390
|
+
const count = u32();
|
|
5391
|
+
for (let i = 0; i < count; i++) {
|
|
5392
|
+
const module = name2();
|
|
5393
|
+
const field = name2();
|
|
5394
|
+
const kind = bytes[at++];
|
|
5395
|
+
if (kind === 0) u32();
|
|
5396
|
+
else if (kind === 1) {
|
|
5397
|
+
at++;
|
|
5398
|
+
limits();
|
|
5399
|
+
} else if (kind === 2) {
|
|
5400
|
+
const l = limits();
|
|
5401
|
+
return { module, name: field, ...l };
|
|
5402
|
+
} else if (kind === 3) at += 2;
|
|
5403
|
+
else if (kind === 4) {
|
|
5404
|
+
at++;
|
|
5405
|
+
u32();
|
|
5406
|
+
}
|
|
5407
|
+
}
|
|
5408
|
+
return void 0;
|
|
5409
|
+
}
|
|
5410
|
+
return void 0;
|
|
5411
|
+
}
|
|
5412
|
+
|
|
5079
5413
|
// src/launcher.ts
|
|
5080
5414
|
var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
5415
|
+
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
5416
|
+
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
5417
|
+
var WASM_MAGIC = [0, 97, 115, 109];
|
|
5081
5418
|
var SHEBANG_MAX = 256;
|
|
5082
5419
|
var NOT_FOUND = 127;
|
|
5083
5420
|
var SHARED_DIRS = ["/tmp", "/home"];
|
|
@@ -5088,13 +5425,43 @@ function baseName(path) {
|
|
|
5088
5425
|
function modulePath(glue) {
|
|
5089
5426
|
return glue.endsWith(".js") ? `${glue.slice(0, -3)}.wasm` : `${glue}.wasm`;
|
|
5090
5427
|
}
|
|
5428
|
+
function isWasm(bytes) {
|
|
5429
|
+
return WASM_MAGIC.every((b, i) => bytes[i] === b);
|
|
5430
|
+
}
|
|
5431
|
+
function shebang(head) {
|
|
5432
|
+
if (head[0] !== 35 || head[1] !== 33) return void 0;
|
|
5433
|
+
return new TextDecoder().decode(head.subarray(0, SHEBANG_MAX)).slice(2).split("\n")[0].trim().split(/[ \t]+/);
|
|
5434
|
+
}
|
|
5435
|
+
function interpreter(head) {
|
|
5436
|
+
const words = shebang(head);
|
|
5437
|
+
if (!words) return "node";
|
|
5438
|
+
if (baseName(words[0]) === "env") words.shift();
|
|
5439
|
+
if (words[0] === "-S") words.shift();
|
|
5440
|
+
return baseName(words[0] ?? "");
|
|
5441
|
+
}
|
|
5442
|
+
function expandDefaults(defaults, env) {
|
|
5443
|
+
const out = {};
|
|
5444
|
+
for (const [key, value] of Object.entries(defaults ?? {})) {
|
|
5445
|
+
let missing3 = false;
|
|
5446
|
+
const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
|
|
5447
|
+
const set2 = Object.hasOwn(env, name2) ? env[name2] : void 0;
|
|
5448
|
+
if (set2 === void 0) missing3 = true;
|
|
5449
|
+
return set2 ?? "";
|
|
5450
|
+
});
|
|
5451
|
+
if (!missing3) out[key] = expanded;
|
|
5452
|
+
}
|
|
5453
|
+
return out;
|
|
5454
|
+
}
|
|
5091
5455
|
function targetOf(command) {
|
|
5092
5456
|
return {
|
|
5457
|
+
abi: command.abi,
|
|
5093
5458
|
glue: command.glue,
|
|
5094
5459
|
wasm: command.wasm,
|
|
5095
5460
|
argv0: command.argv0,
|
|
5096
5461
|
...command.args ? { prefix: command.args } : {},
|
|
5097
|
-
...command.env ? { env: command.env } : {}
|
|
5462
|
+
...command.env ? { env: command.env } : {},
|
|
5463
|
+
...command.unset ? { unset: command.unset } : {},
|
|
5464
|
+
...command.imports ? { imports: command.imports } : {}
|
|
5098
5465
|
};
|
|
5099
5466
|
}
|
|
5100
5467
|
function childHandle(handle) {
|
|
@@ -5126,6 +5493,7 @@ var Launcher = class {
|
|
|
5126
5493
|
zombies = /* @__PURE__ */ new Set();
|
|
5127
5494
|
orphans = /* @__PURE__ */ new Set();
|
|
5128
5495
|
jobs = new JobTable();
|
|
5496
|
+
locks = new LockTable();
|
|
5129
5497
|
ptys = new PtyTable((tty, sig) => this.jobs.signalOwnedForeground(tty, sig));
|
|
5130
5498
|
net = new LoopbackNet();
|
|
5131
5499
|
ca;
|
|
@@ -5154,35 +5522,62 @@ var Launcher = class {
|
|
|
5154
5522
|
const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
|
|
5155
5523
|
if (name2 !== void 0) {
|
|
5156
5524
|
const command = (await this.commands()).get(name2);
|
|
5157
|
-
return command && targetOf(command);
|
|
5525
|
+
return command && !command.script ? targetOf(command) : void 0;
|
|
5158
5526
|
}
|
|
5159
5527
|
const glue = await followLinks(this.base, this.fs.resolvePath(cwd, file));
|
|
5160
5528
|
const linked = COMMAND2.exec(glue)?.[1];
|
|
5161
5529
|
if (linked !== void 0) return this.resolve(`/bin/${linked}`, argv0, cwd);
|
|
5530
|
+
const head = await this.head(glue);
|
|
5531
|
+
if (!head) return void 0;
|
|
5532
|
+
if (isWasm(head)) {
|
|
5533
|
+
return {
|
|
5534
|
+
abi: "wasi",
|
|
5535
|
+
glue,
|
|
5536
|
+
wasm: glue,
|
|
5537
|
+
argv0: baseName(argv0 || file).replace(/\.wasm$/, "")
|
|
5538
|
+
};
|
|
5539
|
+
}
|
|
5540
|
+
if (interpreter(head) !== "node") return void 0;
|
|
5162
5541
|
const wasm = modulePath(glue);
|
|
5163
|
-
if (!await this.base.exists(
|
|
5164
|
-
return { glue, wasm, argv0: baseName(argv0 || file) };
|
|
5542
|
+
if (!await this.base.exists(wasm)) return void 0;
|
|
5543
|
+
return { abi: "emscripten", glue, wasm, argv0: baseName(argv0 || file) };
|
|
5165
5544
|
}
|
|
5166
|
-
async
|
|
5167
|
-
let head;
|
|
5545
|
+
async head(path) {
|
|
5168
5546
|
try {
|
|
5169
|
-
|
|
5170
|
-
0,
|
|
5171
|
-
SHEBANG_MAX
|
|
5172
|
-
);
|
|
5547
|
+
return (await this.base.readFileBuffer(path)).subarray(0, SHEBANG_MAX);
|
|
5173
5548
|
} catch {
|
|
5174
5549
|
return void 0;
|
|
5175
5550
|
}
|
|
5176
|
-
|
|
5177
|
-
|
|
5551
|
+
}
|
|
5552
|
+
async scriptCommand(file) {
|
|
5553
|
+
const name2 = COMMAND2.exec(file)?.[1] ?? (file.includes("/") ? void 0 : file);
|
|
5554
|
+
if (name2 === void 0) return void 0;
|
|
5555
|
+
const command = (await this.commands()).get(name2);
|
|
5556
|
+
return command?.script ? command : void 0;
|
|
5557
|
+
}
|
|
5558
|
+
async interpreted(file, argv, cwd) {
|
|
5559
|
+
const command = await this.scriptCommand(file);
|
|
5560
|
+
const script = command?.script ?? this.fs.resolvePath(cwd, file);
|
|
5561
|
+
const words = shebang(await this.head(script) ?? new Uint8Array());
|
|
5562
|
+
if (!words) return void 0;
|
|
5178
5563
|
if (baseName(words[0]) === "env") words.shift();
|
|
5179
5564
|
const [interp, ...rest] = words;
|
|
5180
|
-
const
|
|
5181
|
-
if (!
|
|
5565
|
+
const found = interp ? await this.resolve(interp, interp, cwd) : void 0;
|
|
5566
|
+
if (!found) return void 0;
|
|
5567
|
+
const target = command ? {
|
|
5568
|
+
...found,
|
|
5569
|
+
env: { ...found.env, ...command.env },
|
|
5570
|
+
unset: [...found.unset ?? [], ...command.unset ?? []]
|
|
5571
|
+
} : found;
|
|
5182
5572
|
const arg = rest.join(" ");
|
|
5183
5573
|
return {
|
|
5184
5574
|
target,
|
|
5185
|
-
args: [
|
|
5575
|
+
args: [
|
|
5576
|
+
...target.prefix ?? [],
|
|
5577
|
+
...arg ? [arg] : [],
|
|
5578
|
+
command ? script : file,
|
|
5579
|
+
...argv.slice(1)
|
|
5580
|
+
]
|
|
5186
5581
|
};
|
|
5187
5582
|
}
|
|
5188
5583
|
async plan(file, argv, cwd) {
|
|
@@ -5199,33 +5594,58 @@ var Launcher = class {
|
|
|
5199
5594
|
const key = `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
5200
5595
|
let module = this.compiled.get(key);
|
|
5201
5596
|
if (!module) {
|
|
5202
|
-
module = this.base.readFileBuffer(path).then((bytes) =>
|
|
5597
|
+
module = this.base.readFileBuffer(path).then(async (bytes) => {
|
|
5598
|
+
const memory = importedMemory(bytes);
|
|
5599
|
+
const compiled = await WebAssembly.compile(bytes);
|
|
5600
|
+
return { module: compiled, ...memory ? { memory } : {} };
|
|
5601
|
+
});
|
|
5203
5602
|
this.compiled.set(key, module);
|
|
5204
5603
|
module.catch(() => this.compiled.delete(key));
|
|
5205
5604
|
}
|
|
5206
5605
|
return module;
|
|
5207
5606
|
});
|
|
5208
5607
|
}
|
|
5608
|
+
async names(path, module) {
|
|
5609
|
+
if (WebAssembly.Module.customSections(module, "name").length > 0) return void 0;
|
|
5610
|
+
const beside = `${path}.names`;
|
|
5611
|
+
if (await this.base.exists(beside)) return beside;
|
|
5612
|
+
const root = PACKAGE_ROOT.exec(path)?.[1];
|
|
5613
|
+
if (root === void 0) return void 0;
|
|
5614
|
+
const optional = `${root}-names${beside.slice(root.length)}`;
|
|
5615
|
+
return await this.base.exists(optional) ? optional : void 0;
|
|
5616
|
+
}
|
|
5617
|
+
async program(target, env) {
|
|
5618
|
+
if (target.abi !== "wasi") {
|
|
5619
|
+
const [glue, { module: module2 }] = await Promise.all([
|
|
5620
|
+
this.base.readFile(target.glue),
|
|
5621
|
+
this.module(target.wasm)
|
|
5622
|
+
]);
|
|
5623
|
+
return { glue, module: module2 };
|
|
5624
|
+
}
|
|
5625
|
+
const { module, memory } = await this.module(target.wasm);
|
|
5626
|
+
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
5627
|
+
const imports = target.imports ? await this.base.readFile(target.imports) : void 0;
|
|
5628
|
+
return {
|
|
5629
|
+
abi: "wasi",
|
|
5630
|
+
glue: "",
|
|
5631
|
+
module,
|
|
5632
|
+
...memory ? { memory } : {},
|
|
5633
|
+
...names ? { names } : {},
|
|
5634
|
+
...imports !== void 0 ? { imports } : {}
|
|
5635
|
+
};
|
|
5636
|
+
}
|
|
5209
5637
|
async launch(planned, req) {
|
|
5210
5638
|
const { target, args } = planned;
|
|
5639
|
+
const env = { ...expandDefaults(target.env, { ...req.env, cwd: req.cwd }), ...req.env };
|
|
5640
|
+
for (const key of target.unset ?? []) delete env[key];
|
|
5211
5641
|
let program;
|
|
5212
5642
|
try {
|
|
5213
|
-
|
|
5214
|
-
this.base.readFile(target.glue),
|
|
5215
|
-
this.module(target.wasm)
|
|
5216
|
-
]);
|
|
5217
|
-
program = { glue, module };
|
|
5643
|
+
program = await this.program(target, env);
|
|
5218
5644
|
} catch (err) {
|
|
5219
5645
|
await req.fds.closeAll();
|
|
5220
5646
|
throw err;
|
|
5221
5647
|
}
|
|
5222
|
-
return this.start({
|
|
5223
|
-
...req,
|
|
5224
|
-
program,
|
|
5225
|
-
argv0: target.argv0,
|
|
5226
|
-
args,
|
|
5227
|
-
env: { ...target.env, ...req.env }
|
|
5228
|
-
});
|
|
5648
|
+
return this.start({ ...req, program, argv0: target.argv0, args, env });
|
|
5229
5649
|
}
|
|
5230
5650
|
start(req) {
|
|
5231
5651
|
const pid = this.nextPid++;
|
|
@@ -5248,6 +5668,7 @@ var Launcher = class {
|
|
|
5248
5668
|
ptys: this.ptys,
|
|
5249
5669
|
net: this.net,
|
|
5250
5670
|
http: new HttpHandles(this.transport),
|
|
5671
|
+
locks: this.locks,
|
|
5251
5672
|
onReap: (child) => this.reaped(child),
|
|
5252
5673
|
...req.fork ? { fork: req.fork } : {},
|
|
5253
5674
|
...req.ppid !== void 0 ? { ppid: req.ppid } : {}
|