@ai-ecoverse/slicc-kernel 1.88.1 → 1.90.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 +47 -11
- package/dist/driver-worker.js +89 -1
- package/dist/driver-worker.js.map +3 -3
- package/dist/index.js +138 -5
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +705 -149
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js.map +2 -2
- package/dist/node-driver-worker.js +89 -1
- package/dist/node-driver-worker.js.map +3 -3
- package/dist/node-process-worker.js +5584 -5259
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +4604 -3976
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +377 -52
- package/dist/process-worker.js.map +4 -4
- package/package.json +2 -2
package/dist/process-worker.js
CHANGED
|
@@ -1070,6 +1070,7 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
1070
1070
|
changing({ op: follow2 ? "chown" : "lchown", path, ...ids }, path);
|
|
1071
1071
|
},
|
|
1072
1072
|
...opts.owners ? { owners: true } : {},
|
|
1073
|
+
...opts.links ? { links: true } : {},
|
|
1073
1074
|
access: (path, mode, kind = "access", nofollow) => {
|
|
1074
1075
|
run({ op: "access", path, mode, arg2: kind, ...nofollow ? { nofollow } : {} }, path);
|
|
1075
1076
|
},
|
|
@@ -1540,7 +1541,12 @@ function createNodeOps(h) {
|
|
|
1540
1541
|
},
|
|
1541
1542
|
readlink(node) {
|
|
1542
1543
|
if (!Fs.isLink(node.mode)) throw new Fs.ErrnoError(wasiErrno("EINVAL"));
|
|
1543
|
-
|
|
1544
|
+
const bridge = bridgeOf(node);
|
|
1545
|
+
const path = liveNodePath(node);
|
|
1546
|
+
if (bridge.links && Fs.sliccReading !== node) {
|
|
1547
|
+
call2(() => bridge.access?.(path, 0, "follow", true));
|
|
1548
|
+
}
|
|
1549
|
+
return call2(() => bridge.readlink(path));
|
|
1544
1550
|
}
|
|
1545
1551
|
};
|
|
1546
1552
|
}
|
|
@@ -1936,6 +1942,63 @@ function useLiveChown(Fs) {
|
|
|
1936
1942
|
Fs.chown(target, uid, gid);
|
|
1937
1943
|
};
|
|
1938
1944
|
}
|
|
1945
|
+
function flushOne(Fs, node) {
|
|
1946
|
+
const s = node.live;
|
|
1947
|
+
if (!s.dirty || s.orphan || !(s.data || s.ranged)) return;
|
|
1948
|
+
try {
|
|
1949
|
+
if (s.ranged) s.ranged.flush();
|
|
1950
|
+
else {
|
|
1951
|
+
const bytes = s.data.slice(0, s.len);
|
|
1952
|
+
pinnedIo(node.mount.opts.bridge, s.handle).writeFile(liveNodePath(node), bytes, true);
|
|
1953
|
+
}
|
|
1954
|
+
} catch (err) {
|
|
1955
|
+
throw toErrno(Fs, err);
|
|
1956
|
+
}
|
|
1957
|
+
s.dirty = false;
|
|
1958
|
+
s.stat = void 0;
|
|
1959
|
+
}
|
|
1960
|
+
function linkable(bridge, path) {
|
|
1961
|
+
try {
|
|
1962
|
+
return bridge.lstat(path).linkable === true;
|
|
1963
|
+
} catch {
|
|
1964
|
+
return false;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
function linkLive(Fs, from, to, follow2) {
|
|
1968
|
+
const target = to.replace(/\/+$/, "");
|
|
1969
|
+
const slash = target.lastIndexOf("/");
|
|
1970
|
+
const name2 = target.slice(slash + 1);
|
|
1971
|
+
const source = Fs.lookupPath(from, { follow: follow2 }).node;
|
|
1972
|
+
const parent = Fs.lookupPath(target.slice(0, slash) || "/", { follow: true }).node;
|
|
1973
|
+
if (!source.live || !parent.live) return false;
|
|
1974
|
+
flushOne(Fs, source);
|
|
1975
|
+
const base = liveNodePath(parent);
|
|
1976
|
+
const bridge = source.mount.opts.bridge;
|
|
1977
|
+
const path = liveNodePath(source);
|
|
1978
|
+
try {
|
|
1979
|
+
bridge.link(path, base === "/" ? `/${name2}` : `${base}/${name2}`);
|
|
1980
|
+
} catch (err) {
|
|
1981
|
+
const refused = toErrno(Fs, err);
|
|
1982
|
+
if (refused.errno !== wasiErrno("EPERM") || linkable(bridge, path)) throw refused;
|
|
1983
|
+
throw new Fs.ErrnoError(wasiErrno("EMLINK"));
|
|
1984
|
+
}
|
|
1985
|
+
source.live.stat = void 0;
|
|
1986
|
+
parent.live.listed = void 0;
|
|
1987
|
+
return true;
|
|
1988
|
+
}
|
|
1989
|
+
function readingLinks(Fs) {
|
|
1990
|
+
const readlink = Fs.readlink?.bind(Fs);
|
|
1991
|
+
if (!readlink) return;
|
|
1992
|
+
Fs.readlink = (path) => {
|
|
1993
|
+
const was = Fs.sliccReading;
|
|
1994
|
+
Fs.sliccReading = Fs.lookupPath(path).node;
|
|
1995
|
+
try {
|
|
1996
|
+
return readlink(path);
|
|
1997
|
+
} finally {
|
|
1998
|
+
Fs.sliccReading = was;
|
|
1999
|
+
}
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
1939
2002
|
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, O_ACCMODE, O_TRUNC, O_PATH, stale;
|
|
1940
2003
|
var init_live_vfs_fs = __esm({
|
|
1941
2004
|
"src/realm/live-vfs-fs.ts"() {
|
|
@@ -1987,6 +2050,7 @@ function mountVfsIntoEmscripten(Fs, deps) {
|
|
|
1987
2050
|
const { plugin, mounted } = mountLiveVfsDirs(Fs, bridge, dirs ?? [], warn);
|
|
1988
2051
|
if (dirs) liveRoot(Fs, bridge);
|
|
1989
2052
|
if (bridge.owners && Fs.lookupPath) useLiveChown(Fs);
|
|
2053
|
+
if (bridge.links && Fs.lookupPath) readingLinks(Fs);
|
|
1990
2054
|
try {
|
|
1991
2055
|
Fs.chdir(deps.cwd);
|
|
1992
2056
|
} catch (err) {
|
|
@@ -2154,21 +2218,46 @@ var init_kernel_streams = __esm({
|
|
|
2154
2218
|
if (typeof this.Fs.stat !== "function") return;
|
|
2155
2219
|
stream.stream_ops = { ...stream.stream_ops, getattr: () => this.Fs.stat?.(name2) ?? {} };
|
|
2156
2220
|
}
|
|
2221
|
+
nameDevice(stream, kind) {
|
|
2222
|
+
this.nameStream(stream, kind === "sealed" ? SEALED_PATH : CLIPBOARD_PATH);
|
|
2223
|
+
}
|
|
2157
2224
|
listSealed() {
|
|
2158
|
-
const
|
|
2225
|
+
const fs = this.Fs;
|
|
2226
|
+
const { analyzePath, mkdev, makedev, registerDevice } = fs;
|
|
2159
2227
|
if (!analyzePath || !mkdev || !makedev) return;
|
|
2160
2228
|
const nodes = [
|
|
2161
2229
|
[SEALED_PATH, 250, this.sys.openSealed],
|
|
2162
2230
|
[CLIPBOARD_PATH, 251, this.sys.openClipboard]
|
|
2163
2231
|
];
|
|
2164
|
-
for (const [path, minor,
|
|
2165
|
-
if (!
|
|
2232
|
+
for (const [path, minor, opener] of nodes) {
|
|
2233
|
+
if (!opener) continue;
|
|
2234
|
+
const dev = makedev.call(fs, 10, minor);
|
|
2235
|
+
registerDevice?.call(fs, dev, {
|
|
2236
|
+
open: (stream) => this.openNode(stream, path, opener)
|
|
2237
|
+
});
|
|
2238
|
+
if (analyzePath.call(fs, path).exists) continue;
|
|
2166
2239
|
try {
|
|
2167
|
-
mkdev.call(
|
|
2240
|
+
const node = mkdev.call(fs, path, dev);
|
|
2241
|
+
if (typeof node === "object" && node !== null) {
|
|
2242
|
+
const made = node;
|
|
2243
|
+
made.node_ops = { ...made.node_ops, getattr: () => sealedStat(minor) };
|
|
2244
|
+
}
|
|
2168
2245
|
} catch {
|
|
2169
2246
|
}
|
|
2170
2247
|
}
|
|
2171
2248
|
}
|
|
2249
|
+
openNode(stream, path, opener) {
|
|
2250
|
+
let kfd;
|
|
2251
|
+
try {
|
|
2252
|
+
kfd = this.call(() => opener.call(this.sys, stream.flags & 3));
|
|
2253
|
+
} catch (e) {
|
|
2254
|
+
this.Fs.closeStream(stream.fd);
|
|
2255
|
+
throw e;
|
|
2256
|
+
}
|
|
2257
|
+
this.attach(stream, kfd, false);
|
|
2258
|
+
this.nameStream(stream, path);
|
|
2259
|
+
if (path === CLIPBOARD_PATH) this.reportClose(kfd);
|
|
2260
|
+
}
|
|
2172
2261
|
reporting = /* @__PURE__ */ new Set();
|
|
2173
2262
|
reportClose(kfd) {
|
|
2174
2263
|
this.reporting.add(kfd);
|
|
@@ -3223,8 +3312,9 @@ function readonlyRefusal(Fs, memory, call2) {
|
|
|
3223
3312
|
follow: follow2
|
|
3224
3313
|
});
|
|
3225
3314
|
const bridge = node.live ? node.mount.opts.bridge : void 0;
|
|
3226
|
-
const
|
|
3227
|
-
|
|
3315
|
+
const stats = bridge;
|
|
3316
|
+
const stat = follow2 ? stats?.stat : stats?.lstat;
|
|
3317
|
+
return stat?.call(stats, liveNodePath(node)).readonly ? -wasiErrno("EROFS") : 0;
|
|
3228
3318
|
} catch {
|
|
3229
3319
|
return 0;
|
|
3230
3320
|
}
|
|
@@ -3256,6 +3346,32 @@ function kernelAccess(imports, fs, memory, glue) {
|
|
|
3256
3346
|
}
|
|
3257
3347
|
});
|
|
3258
3348
|
}
|
|
3349
|
+
function kernelLink(imports, fs, memory, glue) {
|
|
3350
|
+
wrapImport(
|
|
3351
|
+
imports,
|
|
3352
|
+
"linkat",
|
|
3353
|
+
glue,
|
|
3354
|
+
(own) => (olddirfd, oldpath, newdirfd, newpath, flags) => {
|
|
3355
|
+
const Fs = fs();
|
|
3356
|
+
const heap = memory();
|
|
3357
|
+
if (!Fs?.lookupPath || !heap) return own(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
3358
|
+
const at = (dirfd, ptr) => {
|
|
3359
|
+
const name2 = cString(heap, ptr);
|
|
3360
|
+
return name2.startsWith("/") ? name2 : `${baseOf(Fs, dirfd)}/${name2}`;
|
|
3361
|
+
};
|
|
3362
|
+
try {
|
|
3363
|
+
const from = at(olddirfd, oldpath);
|
|
3364
|
+
const to = at(newdirfd, newpath);
|
|
3365
|
+
const follow2 = (flags & AT_SYMLINK_FOLLOW) !== 0;
|
|
3366
|
+
if (linkLive(Fs, from, to, follow2)) return 0;
|
|
3367
|
+
} catch (err) {
|
|
3368
|
+
return -errnoOf(err);
|
|
3369
|
+
}
|
|
3370
|
+
return own(olddirfd, oldpath, newdirfd, newpath, flags);
|
|
3371
|
+
},
|
|
3372
|
+
true
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3259
3375
|
function kernelChdir(Fs) {
|
|
3260
3376
|
const { chdir, lookupPath, ErrnoError } = Fs;
|
|
3261
3377
|
if (!chdir || !lookupPath || !ErrnoError) return;
|
|
@@ -3283,7 +3399,7 @@ function linuxDevices(Fs) {
|
|
|
3283
3399
|
}
|
|
3284
3400
|
}
|
|
3285
3401
|
}
|
|
3286
|
-
var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT2, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, DEVICE_MODES;
|
|
3402
|
+
var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT2, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, AT_SYMLINK_FOLLOW, DEVICE_MODES;
|
|
3287
3403
|
var init_process_fds = __esm({
|
|
3288
3404
|
"src/process/process-fds.ts"() {
|
|
3289
3405
|
"use strict";
|
|
@@ -3318,6 +3434,7 @@ var init_process_fds = __esm({
|
|
|
3318
3434
|
mknodat: "__syscall_mknodat",
|
|
3319
3435
|
umask: "__syscall_umask",
|
|
3320
3436
|
faccessat: "__syscall_faccessat",
|
|
3437
|
+
linkat: "__syscall_linkat",
|
|
3321
3438
|
utimensat: "__syscall_utimensat",
|
|
3322
3439
|
getppid: "slicc_getppid_js",
|
|
3323
3440
|
resizeHeap: "emscripten_resize_heap",
|
|
@@ -3344,6 +3461,7 @@ var init_process_fds = __esm({
|
|
|
3344
3461
|
AT_EACCESS = 512;
|
|
3345
3462
|
W_ACCESS = 2;
|
|
3346
3463
|
X_ACCESS = 1;
|
|
3464
|
+
AT_SYMLINK_FOLLOW = 1024;
|
|
3347
3465
|
DEVICE_MODES = [
|
|
3348
3466
|
["/", 493],
|
|
3349
3467
|
["/dev", 493],
|
|
@@ -3412,7 +3530,8 @@ function kernelEntry(stream, kernel) {
|
|
|
3412
3530
|
if (stream.sliccKernelSocket) {
|
|
3413
3531
|
return { fd: stream.fd, kernel, kind: "socket", flags: stream.flags, ...cloexec };
|
|
3414
3532
|
}
|
|
3415
|
-
const
|
|
3533
|
+
const device2 = stream.path === void 0 ? void 0 : NAMED_DEVICES[stream.path];
|
|
3534
|
+
const kind = stream.sliccKernelFile ? "file" : stream.tty ? "tty" : device2 ?? "stream";
|
|
3416
3535
|
return { fd: stream.fd, kernel, kind, ...cloexec };
|
|
3417
3536
|
}
|
|
3418
3537
|
function describeInherited(Fs, sys, streams, livePath, actions = []) {
|
|
@@ -3462,7 +3581,8 @@ function place(Fs, stream, fd) {
|
|
|
3462
3581
|
function placeholder(Fs, streams, entry) {
|
|
3463
3582
|
if (entry.kind === "socket") return streams.socketStream(entry.flags ?? O_RDWR);
|
|
3464
3583
|
if (entry.kind === "tty") return Fs.open("/dev/tty", O_RDWR);
|
|
3465
|
-
if (entry.kind === "stream" || entry.kind === "clipboard"
|
|
3584
|
+
if (entry.kind === "stream" || entry.kind === "clipboard" || entry.kind === "sealed")
|
|
3585
|
+
return Fs.open("/dev/null", O_RDWR);
|
|
3466
3586
|
Fs.mkdirTree(PLACEHOLDER_DIR);
|
|
3467
3587
|
return Fs.open(`${PLACEHOLDER_DIR}/${entry.fd}`, O_RDWR | O_CREAT3);
|
|
3468
3588
|
}
|
|
@@ -3487,6 +3607,7 @@ function placeKernelStream(Fs, streams, entry) {
|
|
|
3487
3607
|
} else if (entry.kind === "socket") streams.attachSocket(stream, entry.kernel);
|
|
3488
3608
|
else streams.attach(stream, entry.kernel, entry.kind === "tty");
|
|
3489
3609
|
if (entry.kind === "clipboard") streams.reportClose(entry.kernel);
|
|
3610
|
+
if (entry.kind === "sealed" || entry.kind === "clipboard") streams.nameDevice(stream, entry.kind);
|
|
3490
3611
|
if (entry.kind === "tty") streams.nameTerminal(stream);
|
|
3491
3612
|
if (entry.kind === "stream") {
|
|
3492
3613
|
asFifo(stream, streams, entry.desc !== void 0 ? `d${entry.desc}` : `k${entry.kernel}`);
|
|
@@ -3512,7 +3633,7 @@ function restoreForkedStreams(Fs, streams, table) {
|
|
|
3512
3633
|
}
|
|
3513
3634
|
}
|
|
3514
3635
|
}
|
|
3515
|
-
var O_RDWR, O_ACCMODE3, O_CREAT3, O_EXCL2, O_TRUNC3, PLACEHOLDER_DIR, ACCESS, DEVICES, FIFO_MODE, nextStreamIno, streamInos;
|
|
3636
|
+
var O_RDWR, O_ACCMODE3, O_CREAT3, O_EXCL2, O_TRUNC3, PLACEHOLDER_DIR, NAMED_DEVICES, ACCESS, DEVICES, FIFO_MODE, nextStreamIno, streamInos;
|
|
3516
3637
|
var init_process_fork = __esm({
|
|
3517
3638
|
"src/process/process-fork.ts"() {
|
|
3518
3639
|
"use strict";
|
|
@@ -3523,6 +3644,10 @@ var init_process_fork = __esm({
|
|
|
3523
3644
|
O_EXCL2 = 128;
|
|
3524
3645
|
O_TRUNC3 = 512;
|
|
3525
3646
|
PLACEHOLDER_DIR = "/dev/slicc-fd";
|
|
3647
|
+
NAMED_DEVICES = {
|
|
3648
|
+
"/dev/sealed": "sealed",
|
|
3649
|
+
"/dev/clipboard": "clipboard"
|
|
3650
|
+
};
|
|
3526
3651
|
ACCESS = { 0: "read", 1: "write" };
|
|
3527
3652
|
DEVICES = {
|
|
3528
3653
|
"/dev/null": "null",
|
|
@@ -4160,7 +4285,7 @@ var KERNEL_VERSION, OS_RELEASE;
|
|
|
4160
4285
|
var init_version = __esm({
|
|
4161
4286
|
"src/version.ts"() {
|
|
4162
4287
|
"use strict";
|
|
4163
|
-
KERNEL_VERSION = true ? "1.
|
|
4288
|
+
KERNEL_VERSION = true ? "1.90.0" : "0.0.0-dev";
|
|
4164
4289
|
OS_RELEASE = "6.0.0-slicc";
|
|
4165
4290
|
}
|
|
4166
4291
|
});
|
|
@@ -4440,9 +4565,9 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
4440
4565
|
}
|
|
4441
4566
|
return found;
|
|
4442
4567
|
};
|
|
4443
|
-
const
|
|
4444
|
-
const lookup2 =
|
|
4445
|
-
const readdir =
|
|
4568
|
+
const procOps2 = proc.node_ops;
|
|
4569
|
+
const lookup2 = procOps2.lookup?.bind(procOps2);
|
|
4570
|
+
const readdir = procOps2.readdir?.bind(procOps2);
|
|
4446
4571
|
const listAll = (node) => {
|
|
4447
4572
|
const names = new Set(readdir ? readdir(node) : [".", ".."]);
|
|
4448
4573
|
for (const name2 of [...SYSTEM_FILES, "mounts", "sys"]) names.add(name2);
|
|
@@ -4450,7 +4575,7 @@ function useProcfs(Fs, sys, pid, memory = memorySource()) {
|
|
|
4450
4575
|
return [...names];
|
|
4451
4576
|
};
|
|
4452
4577
|
proc.node_ops = {
|
|
4453
|
-
...
|
|
4578
|
+
...procOps2,
|
|
4454
4579
|
lookup: (parent, name2) => {
|
|
4455
4580
|
if (/^[1-9]\d*$/.test(name2)) {
|
|
4456
4581
|
if (!infoOf(Number(name2)) && !listed(Number(name2))) throw error();
|
|
@@ -4831,6 +4956,7 @@ function kernelWrappers(imports, module, deps) {
|
|
|
4831
4956
|
const fsOf = () => ownValue(module, "FS");
|
|
4832
4957
|
noFollowUtimes(imports, fsOf, kernelGlue?.utimensat ?? utimensatOf(module), memory);
|
|
4833
4958
|
kernelAccess(imports, fsOf, memory, kernelGlue);
|
|
4959
|
+
kernelLink(imports, fsOf, memory, kernelGlue);
|
|
4834
4960
|
const glue = ownValue(module, "sliccFdImports");
|
|
4835
4961
|
syncFsync(imports, fsOf, glue);
|
|
4836
4962
|
positionalIo(imports, { glue, fs: fsOf, sys, memory });
|
|
@@ -4838,6 +4964,9 @@ function kernelWrappers(imports, module, deps) {
|
|
|
4838
4964
|
reportGrowth(imports, grown, kernelGlue);
|
|
4839
4965
|
holdWhileStopped(imports, new Int32Array(init.sab, 0, SAB_HEADER_I32), kernelGlue, deps.poll);
|
|
4840
4966
|
}
|
|
4967
|
+
function bridgeFlags(init) {
|
|
4968
|
+
return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
|
|
4969
|
+
}
|
|
4841
4970
|
async function runWasmProcess(init, port2, deps = {}) {
|
|
4842
4971
|
const signals = new SignalGate(
|
|
4843
4972
|
createSyncSabTransport(init.sab, port2, {
|
|
@@ -4942,7 +5071,7 @@ async function runWasmProcess(init, port2, deps = {}) {
|
|
|
4942
5071
|
if (!hasStreams(running)) return runStdioOnly(running, init);
|
|
4943
5072
|
if (init.owners) linuxDevices(running.FS);
|
|
4944
5073
|
const vfs = mountVfsIntoEmscripten(running.FS, {
|
|
4945
|
-
bridge: createSyncFsSabBridge(transport, init
|
|
5074
|
+
bridge: createSyncFsSabBridge(transport, bridgeFlags(init)),
|
|
4946
5075
|
cwd: init.cwd,
|
|
4947
5076
|
warn: deps.warn ?? say(2)
|
|
4948
5077
|
});
|
|
@@ -5097,7 +5226,7 @@ var init_process_runtime = __esm({
|
|
|
5097
5226
|
O_ACCMODE4 = 3;
|
|
5098
5227
|
O_DIRECTORY = 65536;
|
|
5099
5228
|
accessMode = (access) => access === "read" ? O_RDONLY : access === "write" ? O_WRONLY3 : O_RDWR3;
|
|
5100
|
-
PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard"]);
|
|
5229
|
+
PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket", "clipboard", "sealed"]);
|
|
5101
5230
|
GLUE_TRAILER = [
|
|
5102
5231
|
"if (typeof ENV !== 'undefined') Object.assign(ENV, Module.sliccEnv);",
|
|
5103
5232
|
"if (typeof thisProgram !== 'undefined' && Module.thisProgram === '') thisProgram = '';",
|
|
@@ -5126,6 +5255,7 @@ var init_process_runtime = __esm({
|
|
|
5126
5255
|
" mknodat: typeof ___syscall_mknodat === 'function' ? ___syscall_mknodat : undefined,",
|
|
5127
5256
|
" umask: typeof ___syscall_umask === 'function' ? ___syscall_umask : undefined,",
|
|
5128
5257
|
" faccessat: typeof ___syscall_faccessat === 'function' ? ___syscall_faccessat : undefined,",
|
|
5258
|
+
" linkat: typeof ___syscall_linkat === 'function' ? ___syscall_linkat : undefined,",
|
|
5129
5259
|
" utimensat: typeof ___syscall_utimensat === 'function' ? ___syscall_utimensat : undefined,",
|
|
5130
5260
|
" getppid: typeof _slicc_getppid_js === 'function' ? _slicc_getppid_js : undefined,",
|
|
5131
5261
|
" resizeHeap: typeof _emscripten_resize_heap === 'function' ? _emscripten_resize_heap : undefined,",
|
|
@@ -5314,6 +5444,7 @@ function physical(fs, path) {
|
|
|
5314
5444
|
const st = fs.lstat(at);
|
|
5315
5445
|
if (st.isSymbolicLink) {
|
|
5316
5446
|
if (++hops > MAX_LINKS) throw new WasiError("ELOOP");
|
|
5447
|
+
if (fs.links) fs.access?.(at, 0, "follow", true);
|
|
5317
5448
|
const target = fs.readlink(at);
|
|
5318
5449
|
if (target.startsWith("/")) done = [];
|
|
5319
5450
|
todo = [...target.split("/").filter((p) => p !== "" && p !== "."), ...todo];
|
|
@@ -5453,6 +5584,7 @@ function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
|
5453
5584
|
truncate: (p, size) => rewriting(p, () => bridge.truncate?.(p, size))
|
|
5454
5585
|
} : {},
|
|
5455
5586
|
...bridge.owners ? { owners: true } : {},
|
|
5587
|
+
...bridge.links ? { links: true } : {},
|
|
5456
5588
|
invalidate,
|
|
5457
5589
|
touched,
|
|
5458
5590
|
threaded
|
|
@@ -7129,6 +7261,7 @@ var init_wasi_host = __esm({
|
|
|
7129
7261
|
view.setUint32(old, oldLo, true);
|
|
7130
7262
|
view.setUint32(old + 4, oldHi, true);
|
|
7131
7263
|
}) : E.NOSYS,
|
|
7264
|
+
sigmask_poll: (lo, hi, inPtr, outPtr, n, nevents) => this.sigmask ? this.maskedPoll(this.sigmask, [lo, hi], [inPtr, outPtr, n, nevents]) : E.NOSYS,
|
|
7132
7265
|
sigpending_get: (out) => {
|
|
7133
7266
|
if (!this.sigmask) return E.NOSYS;
|
|
7134
7267
|
mem.view().setBigUint64(out, BigInt(this.sigmask.pending()), true);
|
|
@@ -7136,6 +7269,47 @@ var init_wasi_host = __esm({
|
|
|
7136
7269
|
}
|
|
7137
7270
|
});
|
|
7138
7271
|
}
|
|
7272
|
+
poll(inPtr, outPtr, n, nevents) {
|
|
7273
|
+
try {
|
|
7274
|
+
return pollOneoff(
|
|
7275
|
+
{
|
|
7276
|
+
mem: this.mem,
|
|
7277
|
+
fds: this.fds,
|
|
7278
|
+
kernel: this.o.kernel,
|
|
7279
|
+
now: (id) => this.now(id),
|
|
7280
|
+
interruptWakes: this.interruptWakes
|
|
7281
|
+
},
|
|
7282
|
+
inPtr,
|
|
7283
|
+
outPtr,
|
|
7284
|
+
n,
|
|
7285
|
+
nevents
|
|
7286
|
+
);
|
|
7287
|
+
} finally {
|
|
7288
|
+
this.o.fs.invalidate?.();
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
maskedPoll(mask, set, [inPtr, outPtr, n, nevents]) {
|
|
7292
|
+
const old = mask.swap(set[0], set[1]);
|
|
7293
|
+
try {
|
|
7294
|
+
this.mem.view().setUint32(nevents, 0, true);
|
|
7295
|
+
if (mask.deliverUnblocked()) return E.INTR;
|
|
7296
|
+
if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
|
|
7297
|
+
return this.suspend();
|
|
7298
|
+
} finally {
|
|
7299
|
+
mask.deliverUnblocked();
|
|
7300
|
+
mask.restore(old);
|
|
7301
|
+
}
|
|
7302
|
+
}
|
|
7303
|
+
suspend() {
|
|
7304
|
+
for (; ; ) {
|
|
7305
|
+
try {
|
|
7306
|
+
this.o.kernel.call({ op: "fd-select", read: [], write: [], timeoutMs: -1 });
|
|
7307
|
+
} catch (e) {
|
|
7308
|
+
if (e.code === "EINTR") return E.INTR;
|
|
7309
|
+
throw e;
|
|
7310
|
+
}
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7139
7313
|
imports() {
|
|
7140
7314
|
this.cache ??= wrap({
|
|
7141
7315
|
...this.processImports(),
|
|
@@ -7143,25 +7317,7 @@ var init_wasi_host = __esm({
|
|
|
7143
7317
|
...this.statImports(),
|
|
7144
7318
|
...this.pathImports(),
|
|
7145
7319
|
...this.socketImports(),
|
|
7146
|
-
poll_oneoff: (inPtr, outPtr, n, nevents) =>
|
|
7147
|
-
try {
|
|
7148
|
-
return pollOneoff(
|
|
7149
|
-
{
|
|
7150
|
-
mem: this.mem,
|
|
7151
|
-
fds: this.fds,
|
|
7152
|
-
kernel: this.o.kernel,
|
|
7153
|
-
now: (id) => this.now(id),
|
|
7154
|
-
interruptWakes: this.interruptWakes
|
|
7155
|
-
},
|
|
7156
|
-
inPtr,
|
|
7157
|
-
outPtr,
|
|
7158
|
-
n,
|
|
7159
|
-
nevents
|
|
7160
|
-
);
|
|
7161
|
-
} finally {
|
|
7162
|
-
this.o.fs.invalidate?.();
|
|
7163
|
-
}
|
|
7164
|
-
}
|
|
7320
|
+
poll_oneoff: (inPtr, outPtr, n, nevents) => this.poll(inPtr, outPtr, n, nevents)
|
|
7165
7321
|
});
|
|
7166
7322
|
return this.cache;
|
|
7167
7323
|
}
|
|
@@ -8253,15 +8409,15 @@ function procPath(fs, path, follow2) {
|
|
|
8253
8409
|
return result;
|
|
8254
8410
|
}
|
|
8255
8411
|
function frozen(bytes) {
|
|
8256
|
-
const
|
|
8412
|
+
const refuse2 = () => {
|
|
8257
8413
|
throw syncError("EROFS", "/proc");
|
|
8258
8414
|
};
|
|
8259
8415
|
return {
|
|
8260
8416
|
readFile: () => bytes,
|
|
8261
8417
|
pread: (_p, at, n) => bytes.subarray(at, at + n),
|
|
8262
|
-
writeFile:
|
|
8263
|
-
pwrite:
|
|
8264
|
-
truncate:
|
|
8418
|
+
writeFile: refuse2,
|
|
8419
|
+
pwrite: refuse2,
|
|
8420
|
+
truncate: refuse2
|
|
8265
8421
|
};
|
|
8266
8422
|
}
|
|
8267
8423
|
function procfsBridge(fs, tree) {
|
|
@@ -8287,7 +8443,7 @@ function procfsBridge(fs, tree) {
|
|
|
8287
8443
|
return proc(real);
|
|
8288
8444
|
}
|
|
8289
8445
|
};
|
|
8290
|
-
const
|
|
8446
|
+
const readOnly2 = (paths, run) => {
|
|
8291
8447
|
const physical2 = shadowing();
|
|
8292
8448
|
for (const [p, follow2] of paths) {
|
|
8293
8449
|
if (inProc(p) || physical2 && toProc(p, follow2) !== void 0) throw syncError("EROFS", p);
|
|
@@ -8367,15 +8523,15 @@ function procfsBridge(fs, tree) {
|
|
|
8367
8523
|
return [...listed, ["proc", tree.stat("/proc")]];
|
|
8368
8524
|
}
|
|
8369
8525
|
),
|
|
8370
|
-
rename: (from, to) =>
|
|
8526
|
+
rename: (from, to) => readOnly2(
|
|
8371
8527
|
[
|
|
8372
8528
|
[from, false],
|
|
8373
8529
|
[to, false]
|
|
8374
8530
|
],
|
|
8375
8531
|
() => fs.rename(from, to)
|
|
8376
8532
|
),
|
|
8377
|
-
symlink: (target, link) =>
|
|
8378
|
-
link: (from, to, follow2) =>
|
|
8533
|
+
symlink: (target, link) => readOnly2([[link, false]], () => fs.symlink(target, link)),
|
|
8534
|
+
link: (from, to, follow2) => readOnly2(
|
|
8379
8535
|
[
|
|
8380
8536
|
[from, follow2 === true],
|
|
8381
8537
|
[to, false]
|
|
@@ -8407,12 +8563,12 @@ function procfsBridge(fs, tree) {
|
|
|
8407
8563
|
for (const name2 of names) {
|
|
8408
8564
|
const fn = fs[name2];
|
|
8409
8565
|
if (!fn) continue;
|
|
8410
|
-
over[name2] = (p, ...rest2) =>
|
|
8566
|
+
over[name2] = (p, ...rest2) => readOnly2([[p, follow2]], () => fn.call(fs, p, ...rest2));
|
|
8411
8567
|
}
|
|
8412
8568
|
}
|
|
8413
8569
|
const { chown } = fs;
|
|
8414
8570
|
if (chown) {
|
|
8415
|
-
over.chown = (p, uid, gid, follow2) =>
|
|
8571
|
+
over.chown = (p, uid, gid, follow2) => readOnly2([[p, follow2 === true]], () => chown.call(fs, p, uid, gid, follow2));
|
|
8416
8572
|
}
|
|
8417
8573
|
return new Proxy(fs, {
|
|
8418
8574
|
get: (target, key, receiver) => key in over ? over[key] : Reflect.get(target, key, receiver)
|
|
@@ -8593,6 +8749,23 @@ var init_wasi_sigmask = __esm({
|
|
|
8593
8749
|
if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) !== 0) this.deliver();
|
|
8594
8750
|
return E.SUCCESS;
|
|
8595
8751
|
}
|
|
8752
|
+
swap(setLo, setHi) {
|
|
8753
|
+
const old = [this.lo, this.hi];
|
|
8754
|
+
this.lo = setLo & ~LIBC_UNBLOCKABLE;
|
|
8755
|
+
this.hi = setHi | 0;
|
|
8756
|
+
Atomics.store(this.header, SAB_I_BLOCKED, kernelBits(this.lo));
|
|
8757
|
+
return old;
|
|
8758
|
+
}
|
|
8759
|
+
deliverUnblocked() {
|
|
8760
|
+
const now = Atomics.load(this.header, SAB_I_BLOCKED);
|
|
8761
|
+
if ((Atomics.load(this.header, SAB_I_SIGNALS) & ~now) === 0) return false;
|
|
8762
|
+
this.deliver();
|
|
8763
|
+
return true;
|
|
8764
|
+
}
|
|
8765
|
+
restore([lo, hi]) {
|
|
8766
|
+
this.set(SIG_SETMASK, lo, hi, () => {
|
|
8767
|
+
});
|
|
8768
|
+
}
|
|
8596
8769
|
discard(sig) {
|
|
8597
8770
|
Atomics.and(this.header, SAB_I_SIGNALS, ~sigbit(sig));
|
|
8598
8771
|
if (this.process) Atomics.and(this.process, SAB_I_SIGNALS, ~sigbit(sig));
|
|
@@ -10878,7 +11051,7 @@ function descriptors(init, fork, threads) {
|
|
|
10878
11051
|
return { inherited: init.fds ?? [], ...init.program.preopenRoot ? { preopenRoot: true } : {} };
|
|
10879
11052
|
}
|
|
10880
11053
|
function ownersOf(init) {
|
|
10881
|
-
return init.owners ? { owners: true } : {};
|
|
11054
|
+
return { ...init.owners ? { owners: true } : {}, ...init.links ? { links: true } : {} };
|
|
10882
11055
|
}
|
|
10883
11056
|
async function runWasiProcess(init, port2) {
|
|
10884
11057
|
captureBacktraces(init.env);
|
|
@@ -12685,6 +12858,153 @@ var init_js_net = __esm({
|
|
|
12685
12858
|
}
|
|
12686
12859
|
});
|
|
12687
12860
|
|
|
12861
|
+
// src/process/js/js-proc.ts
|
|
12862
|
+
function* procStep(abs, pid, run) {
|
|
12863
|
+
const listing = yield { op: "proc-list" };
|
|
12864
|
+
const mounts = abs === "/proc/mounts" ? yield { op: "mount-list" } : [];
|
|
12865
|
+
const tree = new ProcTree(
|
|
12866
|
+
{ procList: () => listing, mountList: () => mounts },
|
|
12867
|
+
pid,
|
|
12868
|
+
memorySource()
|
|
12869
|
+
);
|
|
12870
|
+
try {
|
|
12871
|
+
return run(tree);
|
|
12872
|
+
} catch (err) {
|
|
12873
|
+
throw new JsCallError(err.code ?? "EIO", abs);
|
|
12874
|
+
}
|
|
12875
|
+
}
|
|
12876
|
+
function readOnly(path) {
|
|
12877
|
+
throw new JsCallError("EROFS", path);
|
|
12878
|
+
}
|
|
12879
|
+
function procWrites(options) {
|
|
12880
|
+
return !!(options?.write || options?.append || options?.create || options?.truncate || options?.exclusive);
|
|
12881
|
+
}
|
|
12882
|
+
function snapshotFile(path, bytes) {
|
|
12883
|
+
let closed = false;
|
|
12884
|
+
const live = () => {
|
|
12885
|
+
if (closed) throw new JsCallError("EBADF", path);
|
|
12886
|
+
};
|
|
12887
|
+
return {
|
|
12888
|
+
fd: -1,
|
|
12889
|
+
path,
|
|
12890
|
+
size: () => {
|
|
12891
|
+
live();
|
|
12892
|
+
return bytes.length;
|
|
12893
|
+
},
|
|
12894
|
+
read: (position, length) => {
|
|
12895
|
+
live();
|
|
12896
|
+
index2(position, "read");
|
|
12897
|
+
index2(length, "read");
|
|
12898
|
+
return bytes.slice(position, position + length);
|
|
12899
|
+
},
|
|
12900
|
+
write: () => {
|
|
12901
|
+
throw new JsCallError("EBADF", path);
|
|
12902
|
+
},
|
|
12903
|
+
truncate: () => {
|
|
12904
|
+
throw new JsCallError("EBADF", path);
|
|
12905
|
+
},
|
|
12906
|
+
sync: () => live(),
|
|
12907
|
+
close: () => {
|
|
12908
|
+
live();
|
|
12909
|
+
closed = true;
|
|
12910
|
+
}
|
|
12911
|
+
};
|
|
12912
|
+
}
|
|
12913
|
+
function promised(file) {
|
|
12914
|
+
const out = { ...file };
|
|
12915
|
+
for (const [name2, value2] of Object.entries(file)) {
|
|
12916
|
+
if (typeof value2 === "function") {
|
|
12917
|
+
out[name2] = (...args) => new Promise((resolve) => resolve(value2(...args)));
|
|
12918
|
+
}
|
|
12919
|
+
}
|
|
12920
|
+
return out;
|
|
12921
|
+
}
|
|
12922
|
+
function procOps(paths, run) {
|
|
12923
|
+
const at = (path) => {
|
|
12924
|
+
const abs = paths.resolve(path);
|
|
12925
|
+
return inProc(abs) ? abs : void 0;
|
|
12926
|
+
};
|
|
12927
|
+
const step = (abs, op) => run(procStep(abs, paths.pid, op));
|
|
12928
|
+
return { at, step };
|
|
12929
|
+
}
|
|
12930
|
+
function withProc(fs, paths, run) {
|
|
12931
|
+
const { at, step } = procOps(paths, run);
|
|
12932
|
+
const out = { ...fs };
|
|
12933
|
+
const pass = fs;
|
|
12934
|
+
const reads = {
|
|
12935
|
+
stat: (tree, abs) => tree.stat(abs, true),
|
|
12936
|
+
lstat: (tree, abs) => tree.stat(abs, false),
|
|
12937
|
+
exists: (tree, abs) => tree.exists(abs),
|
|
12938
|
+
readdir: (tree, abs) => tree.readdir(abs),
|
|
12939
|
+
readlink: (tree, abs) => tree.readlink(abs),
|
|
12940
|
+
readFile: (tree, abs) => tree.read(abs)
|
|
12941
|
+
};
|
|
12942
|
+
for (const [name2, read2] of Object.entries(reads)) {
|
|
12943
|
+
out[name2] = (path, ...rest2) => {
|
|
12944
|
+
const abs = at(path);
|
|
12945
|
+
return abs ? step(abs, (tree) => read2(tree, abs)) : pass[name2]?.(path, ...rest2);
|
|
12946
|
+
};
|
|
12947
|
+
}
|
|
12948
|
+
for (const name2 of WRITES) {
|
|
12949
|
+
out[name2] = (path, ...rest2) => {
|
|
12950
|
+
const abs = at(path);
|
|
12951
|
+
return abs ? run(refuse(abs)) : pass[name2]?.(path, ...rest2);
|
|
12952
|
+
};
|
|
12953
|
+
}
|
|
12954
|
+
for (const name2 of TWO) {
|
|
12955
|
+
out[name2] = (from, to) => {
|
|
12956
|
+
const abs = at(from) ?? at(to);
|
|
12957
|
+
return abs ? run(refuse(abs)) : pass[name2]?.(from, to);
|
|
12958
|
+
};
|
|
12959
|
+
}
|
|
12960
|
+
out.symlink = (target, path) => {
|
|
12961
|
+
const abs = at(path);
|
|
12962
|
+
return abs ? run(refuse(abs)) : pass.symlink?.(target, path);
|
|
12963
|
+
};
|
|
12964
|
+
return out;
|
|
12965
|
+
}
|
|
12966
|
+
function* refuse(abs) {
|
|
12967
|
+
yield* [];
|
|
12968
|
+
return readOnly(abs);
|
|
12969
|
+
}
|
|
12970
|
+
function procOpen(open, paths, run, async = false) {
|
|
12971
|
+
const { at, step } = procOps(paths, run);
|
|
12972
|
+
return (path, options) => {
|
|
12973
|
+
const abs = at(path);
|
|
12974
|
+
if (!abs) return open(path, options);
|
|
12975
|
+
if (procWrites(options)) return run(refuse(abs));
|
|
12976
|
+
return step(abs, (tree) => {
|
|
12977
|
+
const file = snapshotFile(abs, tree.read(abs));
|
|
12978
|
+
return async ? promised(file) : file;
|
|
12979
|
+
});
|
|
12980
|
+
};
|
|
12981
|
+
}
|
|
12982
|
+
function procFsAsync(fs, kernel, paths) {
|
|
12983
|
+
return withProc(fs, paths, (step) => devAsync(kernel, step));
|
|
12984
|
+
}
|
|
12985
|
+
function procFsSync(fs, kernel, paths) {
|
|
12986
|
+
return withProc(fs, paths, (step) => devSync(kernel, step));
|
|
12987
|
+
}
|
|
12988
|
+
function procOpenAsync(open, kernel, paths) {
|
|
12989
|
+
return procOpen(open, paths, (step) => devAsync(kernel, step), true);
|
|
12990
|
+
}
|
|
12991
|
+
function procOpenSync(open, kernel, paths) {
|
|
12992
|
+
return procOpen(open, paths, (step) => devSync(kernel, step));
|
|
12993
|
+
}
|
|
12994
|
+
var WRITES, TWO;
|
|
12995
|
+
var init_js_proc = __esm({
|
|
12996
|
+
"src/process/js/js-proc.ts"() {
|
|
12997
|
+
"use strict";
|
|
12998
|
+
init_procfs();
|
|
12999
|
+
init_wasi_procfs();
|
|
13000
|
+
init_js_dev();
|
|
13001
|
+
init_js_io();
|
|
13002
|
+
init_js_kernel();
|
|
13003
|
+
WRITES = ["mkdir", "rm", "unlink", "chmod", "writeFile"];
|
|
13004
|
+
TWO = ["rename", "link"];
|
|
13005
|
+
}
|
|
13006
|
+
});
|
|
13007
|
+
|
|
12688
13008
|
// src/process/js/js-run.ts
|
|
12689
13009
|
function stdioOf(how) {
|
|
12690
13010
|
if (how === void 0) return "pipe";
|
|
@@ -12849,8 +13169,11 @@ function syncOps(kernel, shared) {
|
|
|
12849
13169
|
infos.delete(fd);
|
|
12850
13170
|
kernel.call({ op: "fd-close", fd });
|
|
12851
13171
|
},
|
|
12852
|
-
open,
|
|
12853
|
-
fs: syncPathOps(kernel, resolve, statOf, open)
|
|
13172
|
+
open: procOpenSync(open, kernel, { resolve, pid: shared.pid }),
|
|
13173
|
+
fs: procFsSync(syncPathOps(kernel, resolve, statOf, open), kernel, {
|
|
13174
|
+
resolve,
|
|
13175
|
+
pid: shared.pid
|
|
13176
|
+
})
|
|
12854
13177
|
};
|
|
12855
13178
|
}
|
|
12856
13179
|
function syncFile(kernel, fd, path, append, forget) {
|
|
@@ -12978,6 +13301,7 @@ var init_js_sync = __esm({
|
|
|
12978
13301
|
init_js_dev();
|
|
12979
13302
|
init_js_io();
|
|
12980
13303
|
init_js_kernel();
|
|
13304
|
+
init_js_proc();
|
|
12981
13305
|
encoder3 = new TextEncoder();
|
|
12982
13306
|
noLane = () => ({ ok: false, errno: "ENOSYS", message: "no sync lane" });
|
|
12983
13307
|
JsSyncKernel = class {
|
|
@@ -13441,7 +13765,7 @@ function createContext(o) {
|
|
|
13441
13765
|
handles.set(fd, handle.invalidate);
|
|
13442
13766
|
return handle.file;
|
|
13443
13767
|
};
|
|
13444
|
-
const fs = pathOps(kernel, resolve, statOf, open);
|
|
13768
|
+
const fs = procFsAsync(pathOps(kernel, resolve, statOf, open), kernel, { resolve, pid: o.pid });
|
|
13445
13769
|
const lane = o.lane ?? laneOf(void 0);
|
|
13446
13770
|
if (o.lane && o.lane !== noLane) kernel.syncLane = o.lane;
|
|
13447
13771
|
const syncKernel = new JsSyncKernel(lane, kernel, unwind);
|
|
@@ -13493,7 +13817,7 @@ function createContext(o) {
|
|
|
13493
13817
|
return { type, tty: type === "tty", seekable: type === "file" };
|
|
13494
13818
|
},
|
|
13495
13819
|
isatty: async (fd) => typeOf(await info(fd)) === "tty",
|
|
13496
|
-
open,
|
|
13820
|
+
open: procOpenAsync(open, kernel, { resolve, pid: o.pid }),
|
|
13497
13821
|
resolve,
|
|
13498
13822
|
fs,
|
|
13499
13823
|
signals: {
|
|
@@ -13700,6 +14024,7 @@ var init_js_context = __esm({
|
|
|
13700
14024
|
init_js_io();
|
|
13701
14025
|
init_js_kernel();
|
|
13702
14026
|
init_js_net();
|
|
14027
|
+
init_js_proc();
|
|
13703
14028
|
init_js_run();
|
|
13704
14029
|
init_js_sync();
|
|
13705
14030
|
init_js_tty();
|