@ai-ecoverse/slicc-kernel 1.64.2 → 1.65.1
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 +7 -1
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +314 -95
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +362 -187
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +297 -76
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +362 -187
- package/dist/process-worker.js.map +4 -4
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -2848,18 +2848,99 @@ function serveClient(port, host) {
|
|
|
2848
2848
|
return { detach, closed: ended.promise };
|
|
2849
2849
|
}
|
|
2850
2850
|
|
|
2851
|
-
// src/fs/
|
|
2851
|
+
// src/fs/path-map.ts
|
|
2852
2852
|
function parentOf2(path) {
|
|
2853
|
+
if (path === "/" || path === "") return void 0;
|
|
2854
|
+
const at = path.lastIndexOf("/");
|
|
2855
|
+
return at <= 0 ? "/" : path.slice(0, at);
|
|
2856
|
+
}
|
|
2857
|
+
var PathMap = class {
|
|
2858
|
+
values = /* @__PURE__ */ new Map();
|
|
2859
|
+
children = /* @__PURE__ */ new Map();
|
|
2860
|
+
get size() {
|
|
2861
|
+
return this.values.size;
|
|
2862
|
+
}
|
|
2863
|
+
has(path) {
|
|
2864
|
+
return this.values.has(path);
|
|
2865
|
+
}
|
|
2866
|
+
get(path) {
|
|
2867
|
+
return this.values.get(path);
|
|
2868
|
+
}
|
|
2869
|
+
keys() {
|
|
2870
|
+
return this.values.keys();
|
|
2871
|
+
}
|
|
2872
|
+
set(path, value) {
|
|
2873
|
+
if (!this.values.has(path)) this.link(path);
|
|
2874
|
+
this.values.set(path, value);
|
|
2875
|
+
return this;
|
|
2876
|
+
}
|
|
2877
|
+
delete(path) {
|
|
2878
|
+
if (!this.values.delete(path)) return false;
|
|
2879
|
+
this.prune(path);
|
|
2880
|
+
return true;
|
|
2881
|
+
}
|
|
2882
|
+
subtree(root) {
|
|
2883
|
+
const out = [];
|
|
2884
|
+
const stack = [root];
|
|
2885
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
2886
|
+
if (this.values.has(path)) out.push(path);
|
|
2887
|
+
const below = this.children.get(path);
|
|
2888
|
+
if (below) for (const child of below) stack.push(child);
|
|
2889
|
+
}
|
|
2890
|
+
return out;
|
|
2891
|
+
}
|
|
2892
|
+
entries() {
|
|
2893
|
+
return this.values.entries();
|
|
2894
|
+
}
|
|
2895
|
+
deleteTree(root) {
|
|
2896
|
+
const stack = [root];
|
|
2897
|
+
for (let path = stack.pop(); path !== void 0; path = stack.pop()) {
|
|
2898
|
+
this.values.delete(path);
|
|
2899
|
+
const below = this.children.get(path);
|
|
2900
|
+
if (below) for (const child of below) stack.push(child);
|
|
2901
|
+
this.children.delete(path);
|
|
2902
|
+
}
|
|
2903
|
+
this.prune(root);
|
|
2904
|
+
}
|
|
2905
|
+
clear() {
|
|
2906
|
+
this.values.clear();
|
|
2907
|
+
this.children.clear();
|
|
2908
|
+
}
|
|
2909
|
+
link(path) {
|
|
2910
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
2911
|
+
const set2 = this.children.get(parent);
|
|
2912
|
+
if (set2?.has(child)) return;
|
|
2913
|
+
if (set2) set2.add(child);
|
|
2914
|
+
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
2915
|
+
child = parent;
|
|
2916
|
+
parent = parentOf2(parent);
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
prune(path) {
|
|
2920
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
2921
|
+
if (this.values.has(child) || this.children.has(child)) return;
|
|
2922
|
+
const set2 = this.children.get(parent);
|
|
2923
|
+
set2?.delete(child);
|
|
2924
|
+
if (set2 && set2.size > 0) return;
|
|
2925
|
+
this.children.delete(parent);
|
|
2926
|
+
child = parent;
|
|
2927
|
+
parent = parentOf2(parent);
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
};
|
|
2931
|
+
|
|
2932
|
+
// src/fs/meta.ts
|
|
2933
|
+
function parentOf3(path) {
|
|
2853
2934
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
2854
2935
|
}
|
|
2855
2936
|
function moved(entry, path) {
|
|
2856
|
-
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir:
|
|
2937
|
+
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf3(path) };
|
|
2857
2938
|
}
|
|
2858
2939
|
function under(path, root) {
|
|
2859
2940
|
return path === root || path.startsWith(`${root}/`);
|
|
2860
2941
|
}
|
|
2861
2942
|
var MemoryMeta = class {
|
|
2862
|
-
entries =
|
|
2943
|
+
entries = new PathMap();
|
|
2863
2944
|
async get(paths) {
|
|
2864
2945
|
return paths.map((path) => this.entries.get(path));
|
|
2865
2946
|
}
|
|
@@ -2872,7 +2953,7 @@ var MemoryMeta = class {
|
|
|
2872
2953
|
}
|
|
2873
2954
|
async move(from, to, root) {
|
|
2874
2955
|
await this.remove([to]);
|
|
2875
|
-
const carried =
|
|
2956
|
+
const carried = this.entries.subtree(from).map((path) => this.entries.get(path));
|
|
2876
2957
|
for (const entry of carried) this.entries.delete(entry.path);
|
|
2877
2958
|
for (const entry of carried) {
|
|
2878
2959
|
const path = to + entry.path.slice(from.length);
|
|
@@ -2881,18 +2962,16 @@ var MemoryMeta = class {
|
|
|
2881
2962
|
this.entries.set(to, moved(root(carried.find((entry) => entry.path === from)), to));
|
|
2882
2963
|
}
|
|
2883
2964
|
async remove(paths) {
|
|
2884
|
-
for (const
|
|
2885
|
-
if (paths.some((path) => under(key, path))) this.entries.delete(key);
|
|
2886
|
-
}
|
|
2965
|
+
for (const path of paths) this.entries.deleteTree(path);
|
|
2887
2966
|
}
|
|
2888
2967
|
async links(dir) {
|
|
2889
|
-
return [...this.entries.
|
|
2968
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => entry.dir === dir);
|
|
2890
2969
|
}
|
|
2891
2970
|
async under(path) {
|
|
2892
|
-
return [...this.entries.
|
|
2971
|
+
return [...this.entries.entries()].map(([, e]) => e).filter((entry) => under(entry.path, path));
|
|
2893
2972
|
}
|
|
2894
2973
|
async all() {
|
|
2895
|
-
return [...this.entries.
|
|
2974
|
+
return [...this.entries.entries()].map(([, e]) => e);
|
|
2896
2975
|
}
|
|
2897
2976
|
};
|
|
2898
2977
|
|
|
@@ -2947,7 +3026,7 @@ function missing(err) {
|
|
|
2947
3026
|
function split(path) {
|
|
2948
3027
|
return path.split("/").filter(Boolean);
|
|
2949
3028
|
}
|
|
2950
|
-
function
|
|
3029
|
+
function parentOf4(path) {
|
|
2951
3030
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
2952
3031
|
}
|
|
2953
3032
|
function baseOf(path) {
|
|
@@ -3016,7 +3095,7 @@ function isHandle(child) {
|
|
|
3016
3095
|
var OpfsFs = class {
|
|
3017
3096
|
root;
|
|
3018
3097
|
meta;
|
|
3019
|
-
dirs =
|
|
3098
|
+
dirs = new PathMap();
|
|
3020
3099
|
checked = /* @__PURE__ */ new WeakMap();
|
|
3021
3100
|
channel;
|
|
3022
3101
|
ranged;
|
|
@@ -3065,7 +3144,7 @@ var OpfsFs = class {
|
|
|
3065
3144
|
async ownerAt(path, entry) {
|
|
3066
3145
|
const own = ownOf(entry);
|
|
3067
3146
|
if (own) return own;
|
|
3068
|
-
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(
|
|
3147
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf4(path));
|
|
3069
3148
|
}
|
|
3070
3149
|
async owned(stat, path, entry) {
|
|
3071
3150
|
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
@@ -3095,7 +3174,7 @@ var OpfsFs = class {
|
|
|
3095
3174
|
async chown(path, change) {
|
|
3096
3175
|
if (!this.owners) return;
|
|
3097
3176
|
if (change.kind === "new") {
|
|
3098
|
-
const at = resolvePath((await this.locate(
|
|
3177
|
+
const at = resolvePath((await this.locate(parentOf4(path), true)).path, baseOf(path));
|
|
3099
3178
|
const { uid = 0, gid = 0, mode } = change;
|
|
3100
3179
|
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
3101
3180
|
}
|
|
@@ -3159,7 +3238,7 @@ var OpfsFs = class {
|
|
|
3159
3238
|
return true;
|
|
3160
3239
|
}
|
|
3161
3240
|
forget(path) {
|
|
3162
|
-
|
|
3241
|
+
this.dirs.deleteTree(path);
|
|
3163
3242
|
}
|
|
3164
3243
|
async inDir(path, op) {
|
|
3165
3244
|
const dir = await this.dir(path);
|
|
@@ -3206,7 +3285,7 @@ var OpfsFs = class {
|
|
|
3206
3285
|
async linkAlong(path) {
|
|
3207
3286
|
for (const entry of await this.meta.get(prefixes(path))) {
|
|
3208
3287
|
if (entry?.link === void 0) continue;
|
|
3209
|
-
if (!await this.real(entry.path) && await this.real(
|
|
3288
|
+
if (!await this.real(entry.path) && await this.real(parentOf4(entry.path))) return entry;
|
|
3210
3289
|
}
|
|
3211
3290
|
return void 0;
|
|
3212
3291
|
}
|
|
@@ -3221,7 +3300,7 @@ var OpfsFs = class {
|
|
|
3221
3300
|
if (!link2) throw err;
|
|
3222
3301
|
if (link2.path === current && !follow2) return { path: current, link: link2 };
|
|
3223
3302
|
const target = `${link2.link}${current.slice(link2.path.length)}`;
|
|
3224
|
-
current = target.split("/").includes("..") ? await this.physical(
|
|
3303
|
+
current = target.split("/").includes("..") ? await this.physical(parentOf4(link2.path), target, hops + 1) : resolvePath(parentOf4(link2.path), target);
|
|
3225
3304
|
}
|
|
3226
3305
|
}
|
|
3227
3306
|
throw fsError("ELOOP", path);
|
|
@@ -3411,8 +3490,8 @@ var OpfsFs = class {
|
|
|
3411
3490
|
if (!missing(err)) throw err;
|
|
3412
3491
|
}
|
|
3413
3492
|
const [entry] = await this.meta.get([path]);
|
|
3414
|
-
const wanted = entry?.link === void 0 ? path : resolvePath(
|
|
3415
|
-
return [resolvePath((await this.locate(
|
|
3493
|
+
const wanted = entry?.link === void 0 ? path : resolvePath(parentOf4(path), entry.link);
|
|
3494
|
+
return [resolvePath((await this.locate(parentOf4(wanted), true)).path, baseOf(wanted)), false];
|
|
3416
3495
|
}
|
|
3417
3496
|
async fileFor(path) {
|
|
3418
3497
|
const [target, existed] = await this.writeTarget(path);
|
|
@@ -3422,7 +3501,7 @@ var OpfsFs = class {
|
|
|
3422
3501
|
dir,
|
|
3423
3502
|
(parent) => parent.getFileHandle(name2, { create: true })
|
|
3424
3503
|
);
|
|
3425
|
-
if (!existed) this.touch(
|
|
3504
|
+
if (!existed) this.touch(parentOf4(target));
|
|
3426
3505
|
return [handle, existed, target];
|
|
3427
3506
|
} catch (err) {
|
|
3428
3507
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
@@ -3492,9 +3571,9 @@ var OpfsFs = class {
|
|
|
3492
3571
|
gid: owner.gid,
|
|
3493
3572
|
...mode ? { mode, parents: mode } : {}
|
|
3494
3573
|
};
|
|
3495
|
-
await this.mkdir(
|
|
3574
|
+
await this.mkdir(parentOf4(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
3496
3575
|
}
|
|
3497
|
-
const parent = await this.locate(
|
|
3576
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
3498
3577
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
3499
3578
|
await parent.handle.getDirectoryHandle(baseOf(path), { create: true });
|
|
3500
3579
|
const made2 = `${parent.path === "/" ? "" : parent.path}/${baseOf(path)}`;
|
|
@@ -3523,7 +3602,7 @@ var OpfsFs = class {
|
|
|
3523
3602
|
this.changed(found.path);
|
|
3524
3603
|
}
|
|
3525
3604
|
await this.meta.remove([found.path]);
|
|
3526
|
-
this.touch(
|
|
3605
|
+
this.touch(parentOf4(found.path));
|
|
3527
3606
|
}
|
|
3528
3607
|
links() {
|
|
3529
3608
|
return false;
|
|
@@ -3535,7 +3614,7 @@ var OpfsFs = class {
|
|
|
3535
3614
|
if (from === to) return;
|
|
3536
3615
|
const source = await this.locate(from, false);
|
|
3537
3616
|
this.forget(source.path);
|
|
3538
|
-
const parent = await this.locate(
|
|
3617
|
+
const parent = await this.locate(parentOf4(to), true);
|
|
3539
3618
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
3540
3619
|
const sourceStat = await this.describe(source);
|
|
3541
3620
|
if (sourceStat.isDirectory && within(destination, source.path)) throw fsError("EINVAL", to);
|
|
@@ -3563,7 +3642,7 @@ var OpfsFs = class {
|
|
|
3563
3642
|
if (source.link) {
|
|
3564
3643
|
if (target?.handle) await this.rm(destination);
|
|
3565
3644
|
await this.meta.move(source.path, destination, carry);
|
|
3566
|
-
this.touch(
|
|
3645
|
+
this.touch(parentOf4(source.path), parent.path);
|
|
3567
3646
|
return;
|
|
3568
3647
|
}
|
|
3569
3648
|
const dir = parent.handle;
|
|
@@ -3585,7 +3664,7 @@ var OpfsFs = class {
|
|
|
3585
3664
|
}
|
|
3586
3665
|
if (copied) await this.restamp(destination, timed2);
|
|
3587
3666
|
this.changed(source.path, destination);
|
|
3588
|
-
this.touch(
|
|
3667
|
+
this.touch(parentOf4(source.path), parent.path);
|
|
3589
3668
|
}
|
|
3590
3669
|
async modified(path) {
|
|
3591
3670
|
const handle = await this.handle(path);
|
|
@@ -3631,7 +3710,7 @@ var OpfsFs = class {
|
|
|
3631
3710
|
for await (const child of handle.values()) await this.copy(child, target, child.name);
|
|
3632
3711
|
}
|
|
3633
3712
|
async symlink(target, path, owner) {
|
|
3634
|
-
const parent = await this.locate(
|
|
3713
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
3635
3714
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
3636
3715
|
const at = resolvePath(parent.path, baseOf(path));
|
|
3637
3716
|
if (await this.locate(at, false).then(
|
|
@@ -3707,7 +3786,7 @@ var OpfsFs = class {
|
|
|
3707
3786
|
let removed = 0;
|
|
3708
3787
|
for (const entry of await this.meta.all()) {
|
|
3709
3788
|
const real = await this.real(entry.path);
|
|
3710
|
-
const stale = entry.link === void 0 ? !real : real || !await this.real(
|
|
3789
|
+
const stale = entry.link === void 0 ? !real : real || !await this.real(parentOf4(entry.path));
|
|
3711
3790
|
if (!stale) continue;
|
|
3712
3791
|
await this.meta.update(entry.path, () => void 0);
|
|
3713
3792
|
removed++;
|
|
@@ -3778,7 +3857,7 @@ function webLocks() {
|
|
|
3778
3857
|
return globalThis.navigator?.locks;
|
|
3779
3858
|
}
|
|
3780
3859
|
var within2 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
3781
|
-
var
|
|
3860
|
+
var parentOf5 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3782
3861
|
var lockName = (instance) => `slicc-unlinked:${instance}`;
|
|
3783
3862
|
var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
|
|
3784
3863
|
var PathGate = class {
|
|
@@ -3911,7 +3990,7 @@ var UnlinkedKeeper = class {
|
|
|
3911
3990
|
await this.serial(async () => {
|
|
3912
3991
|
await Promise.allSettled([this.fs.rename(file.hidden, path)]);
|
|
3913
3992
|
this.unlinkedName(file.hidden);
|
|
3914
|
-
await this.tidy(
|
|
3993
|
+
await this.tidy(parentOf5(file.hidden));
|
|
3915
3994
|
});
|
|
3916
3995
|
}
|
|
3917
3996
|
done4();
|
|
@@ -3952,7 +4031,7 @@ var UnlinkedKeeper = class {
|
|
|
3952
4031
|
}
|
|
3953
4032
|
await this.fs.rm(hidden).catch(() => void 0);
|
|
3954
4033
|
this.unlinkedName(hidden);
|
|
3955
|
-
await this.tidy(
|
|
4034
|
+
await this.tidy(parentOf5(hidden));
|
|
3956
4035
|
}
|
|
3957
4036
|
async linkedName(hidden) {
|
|
3958
4037
|
if (!mayLink(this.fs, hidden)) return;
|
|
@@ -5148,10 +5227,10 @@ async function physicalPathAsync(fs, path) {
|
|
|
5148
5227
|
// src/fs/watch.ts
|
|
5149
5228
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
5150
5229
|
var under2 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
5151
|
-
var
|
|
5230
|
+
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
5152
5231
|
function touches(watcher, changed) {
|
|
5153
5232
|
return watcher.paths.some(
|
|
5154
|
-
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) :
|
|
5233
|
+
(watched) => changed === watched || under2(watched, changed) || (watcher.recursive ? under2(changed, watched) : parentOf6(changed) === watched)
|
|
5155
5234
|
);
|
|
5156
5235
|
}
|
|
5157
5236
|
var FsWatchers = class {
|
|
@@ -5264,6 +5343,23 @@ var CONTINUED_STATUS = 65535;
|
|
|
5264
5343
|
function waitStatus(code, termsig) {
|
|
5265
5344
|
return termsig ? termsig & 127 : (code & 255) << 8;
|
|
5266
5345
|
}
|
|
5346
|
+
function capturing(chunks2, max = Number.POSITIVE_INFINITY, overflow) {
|
|
5347
|
+
let size = 0;
|
|
5348
|
+
let over = false;
|
|
5349
|
+
return (bytes) => {
|
|
5350
|
+
if (over) return;
|
|
5351
|
+
const room = max - size;
|
|
5352
|
+
if (bytes.length > room) {
|
|
5353
|
+
over = true;
|
|
5354
|
+
if (room > 0) chunks2.push(bytes.slice(0, room));
|
|
5355
|
+
size = max;
|
|
5356
|
+
overflow?.();
|
|
5357
|
+
return;
|
|
5358
|
+
}
|
|
5359
|
+
chunks2.push(bytes);
|
|
5360
|
+
size += bytes.length;
|
|
5361
|
+
};
|
|
5362
|
+
}
|
|
5267
5363
|
function concat2(chunks2) {
|
|
5268
5364
|
const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
|
|
5269
5365
|
let offset = 0;
|
|
@@ -5297,15 +5393,15 @@ var ChildTable = class {
|
|
|
5297
5393
|
const fds = new FdTable();
|
|
5298
5394
|
const captured = /* @__PURE__ */ new Map();
|
|
5299
5395
|
try {
|
|
5300
|
-
for (const [n,
|
|
5301
|
-
for (const
|
|
5302
|
-
if (
|
|
5303
|
-
if ("device" in
|
|
5304
|
-
fds.installAt(
|
|
5396
|
+
for (const [n, slot2] of stdio.entries()) fds.installAt(n, this.openSlot(slot2, n, captured));
|
|
5397
|
+
for (const slot2 of inherit2) {
|
|
5398
|
+
if (slot2.fd <= 2) continue;
|
|
5399
|
+
if ("device" in slot2) {
|
|
5400
|
+
fds.installAt(slot2.fd, deviceFile(slot2.device, slot2.access));
|
|
5305
5401
|
continue;
|
|
5306
5402
|
}
|
|
5307
|
-
fds.installAt(
|
|
5308
|
-
if (
|
|
5403
|
+
fds.installAt(slot2.fd, this.parentFds.get(slot2.kernel).retain());
|
|
5404
|
+
if (slot2.flags !== void 0) fds.setStatusFlags(slot2.fd, slot2.flags);
|
|
5309
5405
|
}
|
|
5310
5406
|
} catch (e) {
|
|
5311
5407
|
await fds.closeAll();
|
|
@@ -5346,15 +5442,15 @@ var ChildTable = class {
|
|
|
5346
5442
|
this.watchers.set(pid, listener);
|
|
5347
5443
|
if (child.stoppedBy !== void 0) listener("stopped", child.stoppedBy);
|
|
5348
5444
|
}
|
|
5349
|
-
openSlot(
|
|
5350
|
-
if ("fd" in
|
|
5351
|
-
if ("input" in
|
|
5352
|
-
if ("device" in
|
|
5353
|
-
if ("dir" in
|
|
5354
|
-
if ("capture" in
|
|
5445
|
+
openSlot(slot2, n, captured) {
|
|
5446
|
+
if ("fd" in slot2) return this.parentFds.get(slot2.fd).retain();
|
|
5447
|
+
if ("input" in slot2) return bytesSource(slot2.input);
|
|
5448
|
+
if ("device" in slot2) return deviceFile(slot2.device, slot2.access);
|
|
5449
|
+
if ("dir" in slot2) return heldFile({ dir: slot2.dir });
|
|
5450
|
+
if ("capture" in slot2) {
|
|
5355
5451
|
const chunks2 = [];
|
|
5356
5452
|
captured.set(n, chunks2);
|
|
5357
|
-
return sinkFile((
|
|
5453
|
+
return sinkFile(capturing(chunks2, slot2.max, slot2.overflow));
|
|
5358
5454
|
}
|
|
5359
5455
|
return deviceFile("null");
|
|
5360
5456
|
}
|
|
@@ -5421,11 +5517,11 @@ var ChildTable = class {
|
|
|
5421
5517
|
pids() {
|
|
5422
5518
|
return [...this.children.keys()];
|
|
5423
5519
|
}
|
|
5424
|
-
captured(pid,
|
|
5520
|
+
captured(pid, slot2) {
|
|
5425
5521
|
const slots = this.leftovers.get(pid);
|
|
5426
|
-
const chunks2 = slots?.get(
|
|
5522
|
+
const chunks2 = slots?.get(slot2);
|
|
5427
5523
|
if (!slots || !chunks2) return new Uint8Array(0);
|
|
5428
|
-
slots.delete(
|
|
5524
|
+
slots.delete(slot2);
|
|
5429
5525
|
if (slots.size === 0) this.leftovers.delete(pid);
|
|
5430
5526
|
return concat2(chunks2);
|
|
5431
5527
|
}
|
|
@@ -5711,7 +5807,7 @@ var HeldPaths = class extends Map {
|
|
|
5711
5807
|
return this.revoked.has(path);
|
|
5712
5808
|
}
|
|
5713
5809
|
};
|
|
5714
|
-
var
|
|
5810
|
+
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
5715
5811
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
5716
5812
|
function inodeless(mount, attr2) {
|
|
5717
5813
|
if (attr2.ino !== void 0) return false;
|
|
@@ -5991,7 +6087,7 @@ var MountTable = class {
|
|
|
5991
6087
|
mount.epoch++;
|
|
5992
6088
|
for (const key of [...mount.attrs.keys()]) if (within3(key, path)) mount.attrs.delete(key);
|
|
5993
6089
|
mount.lists.delete(path);
|
|
5994
|
-
mount.lists.delete(
|
|
6090
|
+
mount.lists.delete(parentOf7(path));
|
|
5995
6091
|
for (const key of [...mount.lists.keys()]) if (within3(key, path)) mount.lists.delete(key);
|
|
5996
6092
|
}
|
|
5997
6093
|
async getattr(mount, path, rel2, settled = false) {
|
|
@@ -6067,7 +6163,7 @@ var MountFs = class {
|
|
|
6067
6163
|
if (attr2.kind !== "symlink") return real;
|
|
6068
6164
|
if (hops >= MAX_LINKS6) throw errnoError("ELOOP", path);
|
|
6069
6165
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
6070
|
-
return this.follow(this.base.resolvePath(
|
|
6166
|
+
return this.follow(this.base.resolvePath(parentOf7(real), target), hops + 1, create);
|
|
6071
6167
|
}
|
|
6072
6168
|
async open(mount, rel2, write, owner) {
|
|
6073
6169
|
return await mount.conn.call({
|
|
@@ -6083,8 +6179,8 @@ var MountFs = class {
|
|
|
6083
6179
|
async driverOwner(found, real, owner, directory) {
|
|
6084
6180
|
const { mount, rel: rel2 } = found;
|
|
6085
6181
|
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
6086
|
-
const dir =
|
|
6087
|
-
const above = statOf(await this.table.getattr(mount, dir,
|
|
6182
|
+
const dir = parentOf7(real);
|
|
6183
|
+
const above = statOf(await this.table.getattr(mount, dir, parentOf7(rel2)), dir, mount);
|
|
6088
6184
|
const setgid = (above.mode & S_ISGID4) !== 0;
|
|
6089
6185
|
let mode = owner.mode;
|
|
6090
6186
|
if (directory && setgid) mode = (mode ?? 493) | S_ISGID4;
|
|
@@ -6423,7 +6519,7 @@ var MountFs = class {
|
|
|
6423
6519
|
}
|
|
6424
6520
|
async named(path) {
|
|
6425
6521
|
const at = normalizePath(path);
|
|
6426
|
-
return joinName(await realDir(this,
|
|
6522
|
+
return joinName(await realDir(this, parentOf7(at)), at.slice(at.lastIndexOf("/") + 1));
|
|
6427
6523
|
}
|
|
6428
6524
|
async link(source, target, follow2 = false) {
|
|
6429
6525
|
const from = follow2 ? await realTarget(this, normalizePath(source)) : await this.named(source);
|
|
@@ -7686,6 +7782,7 @@ var HOST_OPS = [
|
|
|
7686
7782
|
"async-resolve",
|
|
7687
7783
|
"async-hold",
|
|
7688
7784
|
"async-cancel",
|
|
7785
|
+
"async-settle",
|
|
7689
7786
|
"async-close"
|
|
7690
7787
|
];
|
|
7691
7788
|
var json3 = (value) => ({ ok: true, kind: "json", json: value });
|
|
@@ -7717,12 +7814,16 @@ var LockTable = class {
|
|
|
7717
7814
|
for (const path of [...this.held.keys()]) this.unlock(pid, path);
|
|
7718
7815
|
}
|
|
7719
7816
|
};
|
|
7817
|
+
var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
|
|
7818
|
+
var unknownSettled = false;
|
|
7720
7819
|
var AsyncOps = class {
|
|
7721
7820
|
next = 1;
|
|
7722
7821
|
results = /* @__PURE__ */ new Map();
|
|
7723
7822
|
ready = [];
|
|
7724
7823
|
running = /* @__PURE__ */ new Map();
|
|
7725
7824
|
waiters = /* @__PURE__ */ new Set();
|
|
7825
|
+
taken = /* @__PURE__ */ new Map();
|
|
7826
|
+
kept = /* @__PURE__ */ new Set();
|
|
7726
7827
|
closed = false;
|
|
7727
7828
|
run;
|
|
7728
7829
|
onReady;
|
|
@@ -7732,6 +7833,7 @@ var AsyncOps = class {
|
|
|
7732
7833
|
}
|
|
7733
7834
|
submit(req) {
|
|
7734
7835
|
const id2 = this.hold();
|
|
7836
|
+
if (KEPT_OPS.has(req.op)) this.kept.add(id2);
|
|
7735
7837
|
const running = new AbortController();
|
|
7736
7838
|
this.running.set(id2, running);
|
|
7737
7839
|
this.run(req, running.signal).then(
|
|
@@ -7755,9 +7857,26 @@ var AsyncOps = class {
|
|
|
7755
7857
|
const result = this.results.get(id2);
|
|
7756
7858
|
if (!result) throw new KernelError("EAGAIN");
|
|
7757
7859
|
this.forget(id2);
|
|
7860
|
+
if (this.kept.delete(id2)) this.taken.set(id2, result);
|
|
7758
7861
|
return result;
|
|
7759
7862
|
}
|
|
7863
|
+
ack(ids) {
|
|
7864
|
+
for (const id2 of ids) this.taken.delete(id2);
|
|
7865
|
+
}
|
|
7866
|
+
async settle(ids) {
|
|
7867
|
+
const never = new AbortController().signal;
|
|
7868
|
+
while (ids.some((id2) => this.running.has(id2))) await this.sleep(void 0, never);
|
|
7869
|
+
return ids.map((id2) => {
|
|
7870
|
+
const result = this.results.get(id2) ?? this.taken.get(id2) ?? null;
|
|
7871
|
+
if (!result && !unknownSettled) {
|
|
7872
|
+
unknownSettled = true;
|
|
7873
|
+
console.warn(`async-settle: no result for op ${id2}; its write counts as made`);
|
|
7874
|
+
}
|
|
7875
|
+
return result;
|
|
7876
|
+
});
|
|
7877
|
+
}
|
|
7760
7878
|
cancel(id2) {
|
|
7879
|
+
this.kept.delete(id2);
|
|
7761
7880
|
this.running.get(id2)?.abort();
|
|
7762
7881
|
this.forget(id2);
|
|
7763
7882
|
}
|
|
@@ -7833,6 +7952,7 @@ async function hostSyscall(req, ctx) {
|
|
|
7833
7952
|
return done2;
|
|
7834
7953
|
case "async-submit":
|
|
7835
7954
|
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
7955
|
+
if (req.ack) ctx.ops.ack(req.ack);
|
|
7836
7956
|
return json3(ctx.ops.submit(req.req));
|
|
7837
7957
|
case "async-wait":
|
|
7838
7958
|
return json3(await ctx.ops.wait(req.timeoutMs, ctx.blocking));
|
|
@@ -7845,6 +7965,8 @@ async function hostSyscall(req, ctx) {
|
|
|
7845
7965
|
case "async-cancel":
|
|
7846
7966
|
ctx.ops.cancel(req.id);
|
|
7847
7967
|
return done2;
|
|
7968
|
+
case "async-settle":
|
|
7969
|
+
return json3(await ctx.ops.settle(req.ids));
|
|
7848
7970
|
case "async-close":
|
|
7849
7971
|
ctx.ops.close();
|
|
7850
7972
|
return done2;
|
|
@@ -9673,8 +9795,8 @@ var KernelTty = class {
|
|
|
9673
9795
|
get canonical() {
|
|
9674
9796
|
return (this.termios.c_lflag & ICANON) !== 0;
|
|
9675
9797
|
}
|
|
9676
|
-
cc(
|
|
9677
|
-
return this.termios.c_cc[
|
|
9798
|
+
cc(slot2) {
|
|
9799
|
+
return this.termios.c_cc[slot2] ?? 0;
|
|
9678
9800
|
}
|
|
9679
9801
|
key(input) {
|
|
9680
9802
|
const { c_iflag, c_lflag } = this.termios;
|
|
@@ -10029,6 +10151,84 @@ function ptySyscall(req, ctx) {
|
|
|
10029
10151
|
}
|
|
10030
10152
|
}
|
|
10031
10153
|
|
|
10154
|
+
// src/kernel/run-child.ts
|
|
10155
|
+
var RUN_CAPTURE_CAP = 64 * 1024 * 1024;
|
|
10156
|
+
var RUN_MAX_BUFFER = 1024 * 1024;
|
|
10157
|
+
function capLimit(maxBuffer) {
|
|
10158
|
+
const asked = maxBuffer === void 0 ? RUN_MAX_BUFFER : maxBuffer;
|
|
10159
|
+
return Math.max(0, Math.min(asked, RUN_CAPTURE_CAP));
|
|
10160
|
+
}
|
|
10161
|
+
function slot(how, n, extra) {
|
|
10162
|
+
if (how === "inherit") return { fd: n };
|
|
10163
|
+
if (how === "ignore") return { none: true };
|
|
10164
|
+
return extra;
|
|
10165
|
+
}
|
|
10166
|
+
function frame2(outcome, out, err) {
|
|
10167
|
+
const head = new TextEncoder().encode(JSON.stringify(outcome));
|
|
10168
|
+
const bytes = new Uint8Array(4 + head.length + out.length + err.length);
|
|
10169
|
+
new DataView(bytes.buffer).setUint32(0, head.length, true);
|
|
10170
|
+
bytes.set(head, 4);
|
|
10171
|
+
bytes.set(out, 4 + head.length);
|
|
10172
|
+
bytes.set(err, 4 + head.length + out.length);
|
|
10173
|
+
return bytes;
|
|
10174
|
+
}
|
|
10175
|
+
async function reaped(deps, pid) {
|
|
10176
|
+
for (; ; ) {
|
|
10177
|
+
try {
|
|
10178
|
+
return (await deps.children.wait(pid, false, deps.interrupt()))[1];
|
|
10179
|
+
} catch (e) {
|
|
10180
|
+
if (!(e instanceof KernelError && e.code === "EINTR") || deps.dying()) throw e;
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10184
|
+
async function runChild(req, deps) {
|
|
10185
|
+
const max = capLimit(req.maxBuffer);
|
|
10186
|
+
let failure;
|
|
10187
|
+
let pid = 0;
|
|
10188
|
+
const kill = () => void Promise.allSettled([deps.kill(pid, req.killSignal)]);
|
|
10189
|
+
const stop = (code) => {
|
|
10190
|
+
if (failure !== void 0) return;
|
|
10191
|
+
failure = code;
|
|
10192
|
+
if (pid !== 0) kill();
|
|
10193
|
+
};
|
|
10194
|
+
const capture = () => ({ capture: true, max, overflow: () => stop("ENOBUFS") });
|
|
10195
|
+
const stdio = [
|
|
10196
|
+
slot(req.stdin, 0, { input: req.input ?? new Uint8Array(0) }),
|
|
10197
|
+
slot(req.stdout, 1, capture()),
|
|
10198
|
+
slot(req.stderr, 2, capture())
|
|
10199
|
+
];
|
|
10200
|
+
try {
|
|
10201
|
+
pid = await deps.children.spawn(
|
|
10202
|
+
{ file: req.file, argv: req.argv, env: req.env, cwd: req.cwd },
|
|
10203
|
+
stdio
|
|
10204
|
+
);
|
|
10205
|
+
} catch (e) {
|
|
10206
|
+
if (!(e instanceof SpawnError)) throw e;
|
|
10207
|
+
const outcome2 = { pid: 0, status: null, error: { code: e.code }, out: 0, err: 0 };
|
|
10208
|
+
return frame2(outcome2, new Uint8Array(0), new Uint8Array(0));
|
|
10209
|
+
}
|
|
10210
|
+
if (failure !== void 0) kill();
|
|
10211
|
+
const timer = req.timeoutMs !== void 0 && req.timeoutMs > 0 ? setTimeout(() => stop("ETIMEDOUT"), req.timeoutMs) : void 0;
|
|
10212
|
+
let status;
|
|
10213
|
+
try {
|
|
10214
|
+
status = await reaped(deps, pid);
|
|
10215
|
+
} finally {
|
|
10216
|
+
clearTimeout(timer);
|
|
10217
|
+
}
|
|
10218
|
+
const out = deps.children.captured(pid, 1);
|
|
10219
|
+
const err = deps.children.captured(pid, 2);
|
|
10220
|
+
const termsig = status & 127;
|
|
10221
|
+
const outcome = {
|
|
10222
|
+
pid,
|
|
10223
|
+
status: termsig ? null : status >> 8 & 255,
|
|
10224
|
+
...termsig ? { signal: termsig } : {},
|
|
10225
|
+
...failure !== void 0 ? { error: { code: failure } } : {},
|
|
10226
|
+
out: out.length,
|
|
10227
|
+
err: err.length
|
|
10228
|
+
};
|
|
10229
|
+
return frame2(outcome, out, err);
|
|
10230
|
+
}
|
|
10231
|
+
|
|
10032
10232
|
// src/kernel/select.ts
|
|
10033
10233
|
function ready(fds, read, write) {
|
|
10034
10234
|
const hangup = /* @__PURE__ */ new Set();
|
|
@@ -10825,6 +11025,8 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
10825
11025
|
"proc-spawn",
|
|
10826
11026
|
"proc-wait",
|
|
10827
11027
|
"proc-captured",
|
|
11028
|
+
"proc-run",
|
|
11029
|
+
"proc-exit",
|
|
10828
11030
|
"proc-fork",
|
|
10829
11031
|
"proc-kill",
|
|
10830
11032
|
"thread-kill",
|
|
@@ -10945,6 +11147,14 @@ var WasmProcess = class {
|
|
|
10945
11147
|
else this.adoptExec(pid);
|
|
10946
11148
|
return pid;
|
|
10947
11149
|
}
|
|
11150
|
+
run(req) {
|
|
11151
|
+
return runChild(req, {
|
|
11152
|
+
children: this.children,
|
|
11153
|
+
kill: (pid, sig) => this.options.kill?.(pid, sig),
|
|
11154
|
+
interrupt: () => this.interrupt.signal,
|
|
11155
|
+
dying: () => this.dying
|
|
11156
|
+
});
|
|
11157
|
+
}
|
|
10948
11158
|
adoptExec(pid) {
|
|
10949
11159
|
this.execChild = pid;
|
|
10950
11160
|
this.children.watch(pid, (state, sig) => state === "stopped" ? this.stop(sig) : this.cont());
|
|
@@ -11493,6 +11703,12 @@ var WasmProcess = class {
|
|
|
11493
11703
|
return { ok: true, kind: "json", json: await this.spawn(req) };
|
|
11494
11704
|
case "proc-wait":
|
|
11495
11705
|
return { ok: true, kind: "json", json: await this.procWait(req, cancelled) };
|
|
11706
|
+
case "proc-run":
|
|
11707
|
+
return { ok: true, kind: "bytes", bytes: await this.run(req) };
|
|
11708
|
+
case "proc-exit":
|
|
11709
|
+
if (!this.options.exitNow) throw new KernelError("ENOSYS");
|
|
11710
|
+
this.options.exitNow(req.status & 255);
|
|
11711
|
+
return DYING;
|
|
11496
11712
|
case "proc-identity":
|
|
11497
11713
|
return { ok: true, kind: "json", json: await this.options.identity?.() ?? null };
|
|
11498
11714
|
case "proc-exec": {
|
|
@@ -11899,6 +12115,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
11899
12115
|
hasPending: () => Atomics.load(header4, SAB_I_SIGNALS) !== 0 || Atomics.load(header4, SAB_I_TIMERS) !== 0,
|
|
11900
12116
|
raise: hooks.raise,
|
|
11901
12117
|
threadKill: hooks.threadKill,
|
|
12118
|
+
...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
|
|
11902
12119
|
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header4, SAB_I_SIGNALS) } : {}
|
|
11903
12120
|
};
|
|
11904
12121
|
}
|
|
@@ -11915,7 +12132,8 @@ function spawnWasmProcess(opts) {
|
|
|
11915
12132
|
header4,
|
|
11916
12133
|
{
|
|
11917
12134
|
raise: (sig) => signal(sig),
|
|
11918
|
-
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig)
|
|
12135
|
+
threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig),
|
|
12136
|
+
...opts.program.abi === "js" ? { exitNow: (code) => exitNow(code) } : {}
|
|
11919
12137
|
},
|
|
11920
12138
|
created3
|
|
11921
12139
|
)
|
|
@@ -11956,6 +12174,9 @@ function spawnWasmProcess(opts) {
|
|
|
11956
12174
|
() => settle(code)
|
|
11957
12175
|
);
|
|
11958
12176
|
};
|
|
12177
|
+
const exitNow = (code) => {
|
|
12178
|
+
queueMicrotask(() => finish(...dying.status(code)));
|
|
12179
|
+
};
|
|
11959
12180
|
const handle = (data) => {
|
|
11960
12181
|
if (data?.type === WASM_PROCESS_EXIT) {
|
|
11961
12182
|
finish(...dying.status(data.code));
|
|
@@ -12691,15 +12912,15 @@ function granted(handle) {
|
|
|
12691
12912
|
);
|
|
12692
12913
|
}
|
|
12693
12914
|
function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
|
|
12694
|
-
const
|
|
12915
|
+
const slot2 = mediumSlot(
|
|
12695
12916
|
async (err, handle) => denied(err) && !await granted(handle),
|
|
12696
12917
|
onLost
|
|
12697
12918
|
);
|
|
12698
12919
|
return {
|
|
12699
|
-
handlers:
|
|
12700
|
-
present:
|
|
12701
|
-
insert: (handle) =>
|
|
12702
|
-
eject:
|
|
12920
|
+
handlers: slot2.handlers,
|
|
12921
|
+
present: slot2.present,
|
|
12922
|
+
insert: (handle) => slot2.insert(handle, kernelFsHandlers(open(handle))),
|
|
12923
|
+
eject: slot2.eject
|
|
12703
12924
|
};
|
|
12704
12925
|
}
|
|
12705
12926
|
|
|
@@ -13577,7 +13798,7 @@ function grantConnect(hook, fetch2, liveness = {}) {
|
|
|
13577
13798
|
async function openHostfs(spec, connect, timing = {}) {
|
|
13578
13799
|
const readonly2 = spec.options?.ro !== void 0;
|
|
13579
13800
|
const { port1, port2 } = new MessageChannel();
|
|
13580
|
-
const
|
|
13801
|
+
const slot2 = mediumSlot(
|
|
13581
13802
|
async (err) => unreachable(err),
|
|
13582
13803
|
() => watching.kick()
|
|
13583
13804
|
);
|
|
@@ -13590,7 +13811,7 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13590
13811
|
});
|
|
13591
13812
|
const served = serveFilesystem(
|
|
13592
13813
|
port2,
|
|
13593
|
-
{ ...
|
|
13814
|
+
{ ...slot2.handlers, mount: ranged2 },
|
|
13594
13815
|
{
|
|
13595
13816
|
symlinks: true,
|
|
13596
13817
|
chmod: true,
|
|
@@ -13604,12 +13825,12 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13604
13825
|
connect: () => connect(spec.source, { readonly: readonly2 }),
|
|
13605
13826
|
up(client) {
|
|
13606
13827
|
active = timed(client, timing.callMs ?? HOSTFS_CALL_MS);
|
|
13607
|
-
|
|
13828
|
+
slot2.insert(client, handlers);
|
|
13608
13829
|
served.invalidate(true);
|
|
13609
13830
|
},
|
|
13610
13831
|
event: (event) => served.invalidate(invalidation(event)),
|
|
13611
13832
|
down() {
|
|
13612
|
-
|
|
13833
|
+
slot2.eject();
|
|
13613
13834
|
served.invalidate(true);
|
|
13614
13835
|
},
|
|
13615
13836
|
...timing
|
|
@@ -13619,7 +13840,7 @@ async function openHostfs(spec, connect, timing = {}) {
|
|
|
13619
13840
|
await watching.ready;
|
|
13620
13841
|
return {
|
|
13621
13842
|
port: port1,
|
|
13622
|
-
present:
|
|
13843
|
+
present: slot2.present,
|
|
13623
13844
|
dispose() {
|
|
13624
13845
|
stop.abort();
|
|
13625
13846
|
port1.close();
|
|
@@ -14922,16 +15143,16 @@ var Launcher = class {
|
|
|
14922
15143
|
}
|
|
14923
15144
|
async insert(target, handle, source) {
|
|
14924
15145
|
const at = normalizePath(target);
|
|
14925
|
-
const
|
|
14926
|
-
if (!
|
|
14927
|
-
if (source !== void 0 && source !== `fsa:${
|
|
15146
|
+
const slot2 = this.removable.get(at);
|
|
15147
|
+
if (!slot2) throw fsError("EINVAL", `${at} is not a removable mount`);
|
|
15148
|
+
if (source !== void 0 && source !== `fsa:${slot2.id}`) {
|
|
14928
15149
|
throw fsError("EINVAL", `${at} is no longer the drive ${source}`);
|
|
14929
15150
|
}
|
|
14930
15151
|
if (!await granted(handle)) throw fsError("EACCES", `${at}: no permission for this folder`);
|
|
14931
|
-
this.inserted.set(
|
|
14932
|
-
await this.media.put(
|
|
14933
|
-
|
|
14934
|
-
|
|
15152
|
+
this.inserted.set(slot2.id, handle);
|
|
15153
|
+
await this.media.put(slot2.id, handle);
|
|
15154
|
+
slot2.medium.insert(handle);
|
|
15155
|
+
slot2.served.invalidate(true);
|
|
14935
15156
|
void this.unlinked.sweep(at);
|
|
14936
15157
|
}
|
|
14937
15158
|
umount(target, detach = false) {
|