@ai-ecoverse/slicc-kernel 1.87.0 → 1.88.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 +12 -7
- package/dist/index.js +1 -0
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +280 -64
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +6 -8
- package/dist/meta.js.map +2 -2
- package/dist/node-process-worker.js +201 -39
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +274 -56
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +201 -39
- package/dist/process-worker.js.map +4 -4
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -97,8 +97,8 @@ var MemoryMeta = class {
|
|
|
97
97
|
async get(paths) {
|
|
98
98
|
return paths.map((path) => this.entries.get(path));
|
|
99
99
|
}
|
|
100
|
-
async fresh(
|
|
101
|
-
return this.
|
|
100
|
+
async fresh(paths) {
|
|
101
|
+
return this.get(paths);
|
|
102
102
|
}
|
|
103
103
|
async update(path, change) {
|
|
104
104
|
this.set(path, change(this.entries.get(path)));
|
|
@@ -196,15 +196,13 @@ var IndexedDbMeta = class {
|
|
|
196
196
|
}
|
|
197
197
|
return paths.map((path) => this.cache.get(path) ?? void 0);
|
|
198
198
|
}
|
|
199
|
-
async fresh(
|
|
199
|
+
async fresh(paths) {
|
|
200
200
|
const [transaction, store] = this.transaction("readonly");
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
await settle(transaction, () => void 0);
|
|
207
|
-
return entry;
|
|
201
|
+
const requests = paths.map((path) => store.get(path));
|
|
202
|
+
return settle(
|
|
203
|
+
transaction,
|
|
204
|
+
() => requests.map((request2) => request2.result ?? void 0)
|
|
205
|
+
);
|
|
208
206
|
}
|
|
209
207
|
async update(path, change) {
|
|
210
208
|
this.settleRemoves();
|
|
@@ -1020,8 +1018,25 @@ var OpfsFs = class {
|
|
|
1020
1018
|
}
|
|
1021
1019
|
counted = [];
|
|
1022
1020
|
async stamp(path) {
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1021
|
+
const paths = [path, "/"];
|
|
1022
|
+
const [entry, root] = this.meta.fresh ? await this.meta.fresh(paths) : await this.meta.get(paths);
|
|
1023
|
+
return `${entry?.writes ?? 0}:${root?.epoch ?? 0}`;
|
|
1024
|
+
}
|
|
1025
|
+
async epoch() {
|
|
1026
|
+
await this.meta.update("/", (entry) => ({
|
|
1027
|
+
...entry,
|
|
1028
|
+
path: "/",
|
|
1029
|
+
epoch: (entry?.epoch ?? 0) + 1
|
|
1030
|
+
}));
|
|
1031
|
+
}
|
|
1032
|
+
async entering(path, change) {
|
|
1033
|
+
if (!isProtected(this.counted, path) && !holdsProtected(this.counted, path)) return change();
|
|
1034
|
+
await this.epoch();
|
|
1035
|
+
try {
|
|
1036
|
+
await change();
|
|
1037
|
+
} finally {
|
|
1038
|
+
await this.epoch();
|
|
1039
|
+
}
|
|
1025
1040
|
}
|
|
1026
1041
|
async counting(target) {
|
|
1027
1042
|
if (!isProtected(this.counted, target)) return;
|
|
@@ -1092,9 +1107,9 @@ var OpfsFs = class {
|
|
|
1092
1107
|
if (fields) await this.meta.update(path, (entry) => ({ ...entry, path, ...fields }));
|
|
1093
1108
|
}
|
|
1094
1109
|
guarded = [];
|
|
1095
|
-
protect(prefixes2) {
|
|
1110
|
+
protect(prefixes2, versions = false) {
|
|
1096
1111
|
this.guarded = prefixes2;
|
|
1097
|
-
this.counted = prefixes2;
|
|
1112
|
+
this.counted = versions ? prefixes2 : [];
|
|
1098
1113
|
}
|
|
1099
1114
|
unguarded() {
|
|
1100
1115
|
return Object.create(this, { guarded: { value: [] } });
|
|
@@ -1674,6 +1689,9 @@ var OpfsFs = class {
|
|
|
1674
1689
|
const parent = await this.locate(parentOf3(to), true);
|
|
1675
1690
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
1676
1691
|
this.refuse(destination, true);
|
|
1692
|
+
await this.entering(destination, () => this.moveTo(source, parent, destination, to));
|
|
1693
|
+
}
|
|
1694
|
+
async moveTo(source, parent, destination, to) {
|
|
1677
1695
|
const sourceStat = await this.describe(source);
|
|
1678
1696
|
if (sourceStat.isDirectory && within2(destination, source.path)) throw fsError("EINVAL", to);
|
|
1679
1697
|
const target = await this.locate(destination, false).catch((err) => {
|
|
@@ -1781,15 +1799,18 @@ var OpfsFs = class {
|
|
|
1781
1799
|
}
|
|
1782
1800
|
const now = Date.now();
|
|
1783
1801
|
const fields = await this.newFields(at, owner && { uid: owner.uid, gid: owner.gid }, false);
|
|
1784
|
-
await this.
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1802
|
+
await this.entering(
|
|
1803
|
+
at,
|
|
1804
|
+
() => this.meta.update(at, () => ({
|
|
1805
|
+
path: at,
|
|
1806
|
+
link: target,
|
|
1807
|
+
dir: parent.path,
|
|
1808
|
+
ino: inodeOf(at),
|
|
1809
|
+
mtimeMs: now,
|
|
1810
|
+
ctimeMs: now,
|
|
1811
|
+
...fields
|
|
1812
|
+
}))
|
|
1813
|
+
);
|
|
1793
1814
|
this.touch(parent.path);
|
|
1794
1815
|
}
|
|
1795
1816
|
async realpath(path, follow2) {
|
|
@@ -7131,8 +7152,12 @@ function closeAll(entry) {
|
|
|
7131
7152
|
|
|
7132
7153
|
// src/commands.ts
|
|
7133
7154
|
var NAME2 = /^[A-Za-z0-9._+-]+$/;
|
|
7155
|
+
var COMMAND_NAME = /^[^/\s\p{Cc}]+$/u;
|
|
7134
7156
|
var ENV_KEY = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
7135
7157
|
var PACKAGE = /\$\{package\}/g;
|
|
7158
|
+
function commandName(name2) {
|
|
7159
|
+
return COMMAND_NAME.test(name2) && name2.isWellFormed() && name2 !== "." && name2 !== "..";
|
|
7160
|
+
}
|
|
7136
7161
|
function inside(pkg, rel2) {
|
|
7137
7162
|
if (typeof rel2 !== "string" || rel2 === "") return void 0;
|
|
7138
7163
|
const clean = rel2.replace(/^\.\//, "");
|
|
@@ -7222,7 +7247,7 @@ function commandsOf(pkg, manifest) {
|
|
|
7222
7247
|
const shared = envOf(pkg, slicc.env);
|
|
7223
7248
|
const out = [];
|
|
7224
7249
|
for (const [name2, raw] of Object.entries(entries)) {
|
|
7225
|
-
if (!
|
|
7250
|
+
if (!commandName(name2) || !raw || typeof raw !== "object") {
|
|
7226
7251
|
continue;
|
|
7227
7252
|
}
|
|
7228
7253
|
const command = commandOf(pkg, name2, raw, packageAbi, shared);
|
|
@@ -7274,18 +7299,86 @@ async function packagesIn(fs, roots) {
|
|
|
7274
7299
|
dirs.push(...await packages(fs, root));
|
|
7275
7300
|
return dirs;
|
|
7276
7301
|
}
|
|
7277
|
-
|
|
7278
|
-
const
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7302
|
+
function binEntries(manifest) {
|
|
7303
|
+
const { bin, name: name2 } = manifest;
|
|
7304
|
+
if (typeof bin === "string") {
|
|
7305
|
+
return typeof name2 === "string" ? [[name2.slice(name2.lastIndexOf("/") + 1), bin]] : [];
|
|
7306
|
+
}
|
|
7307
|
+
return bin && typeof bin === "object" ? Object.entries(bin) : [];
|
|
7308
|
+
}
|
|
7309
|
+
var MAX_HOPS = 40;
|
|
7310
|
+
function physicalResolver(fs) {
|
|
7311
|
+
const known = /* @__PURE__ */ new Map();
|
|
7312
|
+
const pending = /* @__PURE__ */ new Set();
|
|
7313
|
+
let hops = 0;
|
|
7314
|
+
const step = async (path) => {
|
|
7315
|
+
if (path === "/") return { path, file: false };
|
|
7316
|
+
const slash = path.lastIndexOf("/");
|
|
7317
|
+
const parent = await resolve2(path.slice(0, slash) || "/");
|
|
7318
|
+
if (parent === void 0) return void 0;
|
|
7319
|
+
const at = resolvePath(parent.path, path.slice(slash + 1));
|
|
7320
|
+
const st = await fs.lstat(at).catch(() => void 0);
|
|
7321
|
+
if (!st?.isSymbolicLink) return st ? { path: at, file: st.isFile === true } : void 0;
|
|
7322
|
+
const target = await fs.readlink(at).catch(() => void 0);
|
|
7323
|
+
if (target === void 0 || ++hops > MAX_HOPS) return void 0;
|
|
7324
|
+
return resolve2(resolvePath(parent.path, target));
|
|
7325
|
+
};
|
|
7326
|
+
const resolve2 = (path) => {
|
|
7327
|
+
if (pending.has(path)) return Promise.resolve(void 0);
|
|
7328
|
+
let found = known.get(path);
|
|
7329
|
+
if (!found) {
|
|
7330
|
+
pending.add(path);
|
|
7331
|
+
found = step(path).finally(() => pending.delete(path));
|
|
7332
|
+
known.set(path, found);
|
|
7285
7333
|
}
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7334
|
+
return found;
|
|
7335
|
+
};
|
|
7336
|
+
return (path) => {
|
|
7337
|
+
hops = 0;
|
|
7338
|
+
return resolve2(path);
|
|
7339
|
+
};
|
|
7340
|
+
}
|
|
7341
|
+
async function binCommandsOf(physical, pkg, manifest, taken) {
|
|
7342
|
+
const entries = binEntries(manifest);
|
|
7343
|
+
if (entries.length === 0) return [];
|
|
7344
|
+
const home = (await physical(pkg))?.path;
|
|
7345
|
+
const out = [];
|
|
7346
|
+
for (const [name2, rel2] of entries) {
|
|
7347
|
+
if (taken.has(name2) || !commandName(name2)) continue;
|
|
7348
|
+
const script = inside(pkg, rel2);
|
|
7349
|
+
if (!script) continue;
|
|
7350
|
+
const real = await physical(script);
|
|
7351
|
+
if (!real?.file || !real.path.startsWith(`${home}/`)) continue;
|
|
7352
|
+
out.push({
|
|
7353
|
+
name: name2,
|
|
7354
|
+
abi: "emscripten",
|
|
7355
|
+
glue: script,
|
|
7356
|
+
wasm: script,
|
|
7357
|
+
argv0: name2,
|
|
7358
|
+
script,
|
|
7359
|
+
bin: true
|
|
7360
|
+
});
|
|
7361
|
+
}
|
|
7362
|
+
return out;
|
|
7363
|
+
}
|
|
7364
|
+
async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY) {
|
|
7365
|
+
const found = /* @__PURE__ */ new Map();
|
|
7366
|
+
const physical = physicalResolver(fs);
|
|
7367
|
+
for (const [index, root] of (typeof modules === "string" ? [modules] : modules).entries()) {
|
|
7368
|
+
for (const pkg of await packages(fs, root)) {
|
|
7369
|
+
let manifest;
|
|
7370
|
+
try {
|
|
7371
|
+
manifest = JSON.parse(await fs.readFile(`${pkg}/package.json`));
|
|
7372
|
+
} catch {
|
|
7373
|
+
continue;
|
|
7374
|
+
}
|
|
7375
|
+
const own = commandsOf(pkg, manifest);
|
|
7376
|
+
const named = new Set(own.map((command) => command.name));
|
|
7377
|
+
const bins = index >= binsFrom ? await binCommandsOf(physical, pkg, manifest, named) : [];
|
|
7378
|
+
for (const command of [...own, ...bins]) {
|
|
7379
|
+
if (!found.has(command.name))
|
|
7380
|
+
found.set(command.name, await withPackagePaths(fs, pkg, command));
|
|
7381
|
+
}
|
|
7289
7382
|
}
|
|
7290
7383
|
}
|
|
7291
7384
|
if (!found.has("sh") && found.has("bash")) {
|
|
@@ -7744,7 +7837,7 @@ var FreshModules = class {
|
|
|
7744
7837
|
};
|
|
7745
7838
|
|
|
7746
7839
|
// src/fs/physical-path.ts
|
|
7747
|
-
var
|
|
7840
|
+
var MAX_HOPS2 = 40;
|
|
7748
7841
|
function start(path) {
|
|
7749
7842
|
return { done: [], todo: path.split("/").filter((p) => p !== ""), hops: 0 };
|
|
7750
7843
|
}
|
|
@@ -7769,7 +7862,7 @@ function rest(walk2, part) {
|
|
|
7769
7862
|
return lexical(`/${[...walk2.done, part, ...walk2.todo].join("/")}`);
|
|
7770
7863
|
}
|
|
7771
7864
|
function follow(walk2, target) {
|
|
7772
|
-
if (++walk2.hops >
|
|
7865
|
+
if (++walk2.hops > MAX_HOPS2) return false;
|
|
7773
7866
|
if (target.startsWith("/")) walk2.done.length = 0;
|
|
7774
7867
|
walk2.todo = [...target.split("/").filter((p) => p !== ""), ...walk2.todo];
|
|
7775
7868
|
return true;
|
|
@@ -9975,7 +10068,7 @@ async function dispatchOne(entry, req) {
|
|
|
9975
10068
|
}
|
|
9976
10069
|
|
|
9977
10070
|
// src/realm/sync-sab-wire.ts
|
|
9978
|
-
var SAB_HEADER_I32 =
|
|
10071
|
+
var SAB_HEADER_I32 = 18;
|
|
9979
10072
|
var SAB_CLOCK_OFFSET = SAB_HEADER_I32 * 4;
|
|
9980
10073
|
var SAB_CLOCK_I64 = 3;
|
|
9981
10074
|
var SAB_HEADER_BYTES = SAB_CLOCK_OFFSET + SAB_CLOCK_I64 * 8;
|
|
@@ -9995,6 +10088,7 @@ var SAB_I_OFFSET_HI = 12;
|
|
|
9995
10088
|
var SAB_I_KILLED = 13;
|
|
9996
10089
|
var SAB_I_ASYNC = 14;
|
|
9997
10090
|
var SAB_I_STOP = 15;
|
|
10091
|
+
var SAB_I_BLOCKED = 16;
|
|
9998
10092
|
var U32 = 2 ** 32;
|
|
9999
10093
|
function storeU53(header3, lo, hi, value) {
|
|
10000
10094
|
Atomics.store(header3, hi, Math.floor(value / U32));
|
|
@@ -10520,12 +10614,32 @@ function mountTable(mounts = []) {
|
|
|
10520
10614
|
`;
|
|
10521
10615
|
}
|
|
10522
10616
|
|
|
10617
|
+
// src/version.ts
|
|
10618
|
+
var KERNEL_VERSION = true ? "1.88.0" : "0.0.0-dev";
|
|
10619
|
+
var OS_RELEASE = "6.0.0-slicc";
|
|
10620
|
+
function procVersion() {
|
|
10621
|
+
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
10622
|
+
`;
|
|
10623
|
+
}
|
|
10624
|
+
|
|
10523
10625
|
// src/process/procfs.ts
|
|
10524
10626
|
var HZ = 100;
|
|
10525
10627
|
var KIB = 1024;
|
|
10526
10628
|
var FALLBACK_MEMORY = 4 * KIB * KIB * KIB;
|
|
10527
10629
|
var PID_FILES = ["cmdline", "comm", "stat", "statm", "status"];
|
|
10528
|
-
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime"];
|
|
10630
|
+
var SYSTEM_FILES = ["loadavg", "meminfo", "stat", "uptime", "version"];
|
|
10631
|
+
var SYS_TREE = {
|
|
10632
|
+
kernel: { osrelease: `${OS_RELEASE}
|
|
10633
|
+
`, ostype: "Linux\n" }
|
|
10634
|
+
};
|
|
10635
|
+
function sysEntry(parts2) {
|
|
10636
|
+
let at = SYS_TREE;
|
|
10637
|
+
for (const part of parts2) {
|
|
10638
|
+
if (typeof at !== "object" || !Object.hasOwn(at, part)) return void 0;
|
|
10639
|
+
at = at[part];
|
|
10640
|
+
}
|
|
10641
|
+
return at;
|
|
10642
|
+
}
|
|
10529
10643
|
function commOf(info) {
|
|
10530
10644
|
const name2 = info.argv[0] ?? "";
|
|
10531
10645
|
return name2.slice(name2.lastIndexOf("/") + 1).slice(0, 15);
|
|
@@ -10613,7 +10727,7 @@ function pidStatus(info) {
|
|
|
10613
10727
|
"SigQ: 0/0",
|
|
10614
10728
|
"SigPnd: 0000000000000000",
|
|
10615
10729
|
"ShdPnd: 0000000000000000",
|
|
10616
|
-
|
|
10730
|
+
`SigBlk: ${sigMask(info.sigBlk)}`,
|
|
10617
10731
|
`SigIgn: ${sigMask(info.sigIgn)}`,
|
|
10618
10732
|
`SigCgt: ${sigMask(info.sigCgt)}`,
|
|
10619
10733
|
""
|
|
@@ -10649,6 +10763,7 @@ function memoryInfo(source, used = 0) {
|
|
|
10649
10763
|
].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
|
|
10650
10764
|
}
|
|
10651
10765
|
function systemFile(name2, listing, now, memory) {
|
|
10766
|
+
if (name2 === "version") return procVersion();
|
|
10652
10767
|
const up = Math.max(0, now - listing.boot) / 1e3;
|
|
10653
10768
|
if (name2 === "uptime") return `${up.toFixed(2)} ${up.toFixed(2)}
|
|
10654
10769
|
`;
|
|
@@ -10739,11 +10854,17 @@ var ProcTree = class {
|
|
|
10739
10854
|
names: () => [
|
|
10740
10855
|
...SYSTEM_NAMES,
|
|
10741
10856
|
"mounts",
|
|
10857
|
+
"sys",
|
|
10742
10858
|
"self",
|
|
10743
10859
|
...this.listing().processes.map((p) => String(p.pid))
|
|
10744
10860
|
]
|
|
10745
10861
|
};
|
|
10746
10862
|
}
|
|
10863
|
+
if (top === "sys") {
|
|
10864
|
+
const entry = sysEntry(parts2.slice(1));
|
|
10865
|
+
if (typeof entry === "string") return { kind: "file", content: () => entry };
|
|
10866
|
+
return entry && { kind: "dir", names: () => Object.keys(entry) };
|
|
10867
|
+
}
|
|
10747
10868
|
if (top === "self") {
|
|
10748
10869
|
return leaf === void 0 ? { kind: "link", target: String(this.pid) } : void 0;
|
|
10749
10870
|
}
|
|
@@ -10821,7 +10942,7 @@ var ProcTree = class {
|
|
|
10821
10942
|
}
|
|
10822
10943
|
}
|
|
10823
10944
|
};
|
|
10824
|
-
var
|
|
10945
|
+
var MAX_HOPS3 = 40;
|
|
10825
10946
|
function* procWalk(path, follow2) {
|
|
10826
10947
|
let done4 = [];
|
|
10827
10948
|
let todo = path.split("/").filter((part) => part !== "");
|
|
@@ -10840,7 +10961,7 @@ function* procWalk(path, follow2) {
|
|
|
10840
10961
|
if (!follow2 && todo.length === 0) return void 0;
|
|
10841
10962
|
const target = yield { at, check: todo.find((next2) => next2 !== ".") === ".." };
|
|
10842
10963
|
if (typeof target === "string") {
|
|
10843
|
-
if (++hops >
|
|
10964
|
+
if (++hops > MAX_HOPS3) return void 0;
|
|
10844
10965
|
[done4, todo] = throughLink(target, done4, todo);
|
|
10845
10966
|
} else {
|
|
10846
10967
|
broken ??= refusalOf(target);
|
|
@@ -12399,11 +12520,12 @@ var VfsNodes = class {
|
|
|
12399
12520
|
byId = /* @__PURE__ */ new Map();
|
|
12400
12521
|
keepsOnDisk = false;
|
|
12401
12522
|
fs;
|
|
12402
|
-
entries
|
|
12523
|
+
entries;
|
|
12403
12524
|
onClosed;
|
|
12404
|
-
constructor(fs, onClosed) {
|
|
12525
|
+
constructor(fs, onClosed, entries = /* @__PURE__ */ new Map()) {
|
|
12405
12526
|
this.fs = fs;
|
|
12406
12527
|
this.onClosed = onClosed;
|
|
12528
|
+
this.entries = entries;
|
|
12407
12529
|
}
|
|
12408
12530
|
async onEntry(path, op) {
|
|
12409
12531
|
const key = await this.entryKey(path);
|
|
@@ -12893,6 +13015,7 @@ var HOSTS_ONLY = new Resolver({ routes: new Routes() });
|
|
|
12893
13015
|
var WasmProcess = class {
|
|
12894
13016
|
exited = false;
|
|
12895
13017
|
children;
|
|
13018
|
+
deathSignals = /* @__PURE__ */ new Map();
|
|
12896
13019
|
caught = 0;
|
|
12897
13020
|
ignored = 0;
|
|
12898
13021
|
inherited = 0;
|
|
@@ -12927,7 +13050,10 @@ var WasmProcess = class {
|
|
|
12927
13050
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
12928
13051
|
if (!options.nodes) options.openFiles?.add(this.nodes);
|
|
12929
13052
|
this.children.onChildState = () => this.signal(SIG.CHLD);
|
|
12930
|
-
this.children.onReap =
|
|
13053
|
+
this.children.onReap = (pid2) => {
|
|
13054
|
+
this.deathSignals.delete(pid2);
|
|
13055
|
+
options.onReap?.(pid2);
|
|
13056
|
+
};
|
|
12931
13057
|
}
|
|
12932
13058
|
ignores(bit) {
|
|
12933
13059
|
return (this.signalMasks().ignored & bit) !== 0;
|
|
@@ -12955,6 +13081,10 @@ var WasmProcess = class {
|
|
|
12955
13081
|
if (sig === SIG.STOP) return this.stop(sig);
|
|
12956
13082
|
const bit = sigbit(sig);
|
|
12957
13083
|
if (this.ignores(bit)) return "ignore";
|
|
13084
|
+
if (((this.options.blockedBits?.() ?? 0) & bit) !== 0) {
|
|
13085
|
+
this.options.onPending?.(sig);
|
|
13086
|
+
return "deliver";
|
|
13087
|
+
}
|
|
12958
13088
|
if (!(this.caught & bit)) {
|
|
12959
13089
|
const action = defaultAction(sig);
|
|
12960
13090
|
return action === "stop" ? this.stop(sig) : action;
|
|
@@ -12971,16 +13101,27 @@ var WasmProcess = class {
|
|
|
12971
13101
|
return "deliver";
|
|
12972
13102
|
}
|
|
12973
13103
|
async spawn(req) {
|
|
12974
|
-
const { file, argv, argv0, env, cwd, stdio, inherit: inherit2, exec, pgid, session } = req;
|
|
13104
|
+
const { file, argv, argv0, env, cwd, stdio, inherit: inherit2, exec, pgid, session, deathSignal } = req;
|
|
13105
|
+
if (deathSignal !== void 0 && (exec || !isSignal(deathSignal))) {
|
|
13106
|
+
throw new KernelError("EINVAL");
|
|
13107
|
+
}
|
|
12975
13108
|
const group = { ...pgid !== void 0 ? { pgid } : {}, ...session ? { session } : {} };
|
|
12976
13109
|
const named = argv0 !== void 0 ? { argv0 } : {};
|
|
12977
13110
|
const spawned = { file, argv, ...named, env, cwd, ...group, ...exec ? { exec } : {} };
|
|
12978
13111
|
const pid = await this.children.spawn(spawned, stdio, inherit2);
|
|
13112
|
+
if (deathSignal !== void 0) this.onDeath(pgid === 0 || session ? -pid : pid, deathSignal);
|
|
12979
13113
|
if (!exec) return pid;
|
|
12980
13114
|
if (this.killed) void Promise.allSettled([this.options.kill?.(pid, SIG.KILL)]);
|
|
12981
13115
|
else this.adoptExec(pid);
|
|
12982
13116
|
return pid;
|
|
12983
13117
|
}
|
|
13118
|
+
onDeath(target, sig) {
|
|
13119
|
+
if (this.exited) this.sendDeath(target, sig);
|
|
13120
|
+
else this.deathSignals.set(target, sig);
|
|
13121
|
+
}
|
|
13122
|
+
sendDeath(target, sig) {
|
|
13123
|
+
void Promise.resolve(this.options.kill?.(target, sig)).catch(() => void 0);
|
|
13124
|
+
}
|
|
12984
13125
|
async killSelf(sig, target, probe) {
|
|
12985
13126
|
if (!this.options.exitSignal) throw new KernelError("ENOSYS");
|
|
12986
13127
|
if (!isSignal(sig) || defaultAction(sig) !== "terminate") throw new KernelError("EINVAL");
|
|
@@ -13879,6 +14020,8 @@ var WasmProcess = class {
|
|
|
13879
14020
|
this.interrupt.abort();
|
|
13880
14021
|
this.options.locks?.release(this.pid);
|
|
13881
14022
|
this.asyncOps.close();
|
|
14023
|
+
for (const [target, sig] of this.deathSignals) this.sendDeath(target, sig);
|
|
14024
|
+
this.deathSignals.clear();
|
|
13882
14025
|
for (const pid of this.children.pids()) this.options.onReap?.(pid);
|
|
13883
14026
|
await this.stampClipboards();
|
|
13884
14027
|
await this.fds.closeAll();
|
|
@@ -13958,19 +14101,25 @@ var Dying = class {
|
|
|
13958
14101
|
}
|
|
13959
14102
|
};
|
|
13960
14103
|
function killThread(thread, caught, sig) {
|
|
13961
|
-
if (!thread
|
|
14104
|
+
if (!thread) return false;
|
|
14105
|
+
const held = (Atomics.load(thread.header, SAB_I_BLOCKED) & sigbit(sig)) !== 0;
|
|
14106
|
+
if (!held && (caught & sigbit(sig)) === 0) return false;
|
|
13962
14107
|
Atomics.or(thread.header, SAB_I_SIGNALS, sigbit(sig));
|
|
14108
|
+
if (held) return true;
|
|
13963
14109
|
Atomics.notify(thread.header, SAB_I_SIGNALS);
|
|
13964
14110
|
const blocked = thread.interrupt;
|
|
13965
14111
|
thread.interrupt = new AbortController();
|
|
13966
14112
|
blocked.abort();
|
|
13967
14113
|
return true;
|
|
13968
14114
|
}
|
|
14115
|
+
function unblocked(header3) {
|
|
14116
|
+
return Atomics.load(header3, SAB_I_SIGNALS) & ~Atomics.load(header3, SAB_I_BLOCKED);
|
|
14117
|
+
}
|
|
13969
14118
|
function threadSignalsOf(sab) {
|
|
13970
14119
|
return { header: new Int32Array(sab, 0, SAB_HEADER_I32), interrupt: new AbortController() };
|
|
13971
14120
|
}
|
|
13972
14121
|
function threadCancel(thread) {
|
|
13973
|
-
return
|
|
14122
|
+
return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
13974
14123
|
}
|
|
13975
14124
|
function notifiers(header3) {
|
|
13976
14125
|
return {
|
|
@@ -14095,15 +14244,16 @@ function processOptions(opts, header3, hooks, created3) {
|
|
|
14095
14244
|
resolver: opts.resolver,
|
|
14096
14245
|
...notifiers(header3),
|
|
14097
14246
|
onTimer: (which) => void Atomics.or(header3, SAB_I_TIMERS, 1 << which),
|
|
14098
|
-
hasPending: () =>
|
|
14247
|
+
hasPending: () => unblocked(header3) !== 0 || Atomics.load(header3, SAB_I_TIMERS) !== 0,
|
|
14099
14248
|
raise: hooks.raise,
|
|
14100
14249
|
threadKill: hooks.threadKill,
|
|
14101
14250
|
...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
|
|
14102
14251
|
...hooks.exitSignal ? { exitSignal: hooks.exitSignal } : {},
|
|
14103
|
-
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header3, SAB_I_SIGNALS) } : {}
|
|
14252
|
+
...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header3, SAB_I_SIGNALS) } : {},
|
|
14253
|
+
...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header3, SAB_I_BLOCKED) } : {}
|
|
14104
14254
|
};
|
|
14105
14255
|
}
|
|
14106
|
-
function threadInit(opts, program, sab, cred, thread) {
|
|
14256
|
+
function threadInit(opts, program, sab, cred, thread, main) {
|
|
14107
14257
|
return {
|
|
14108
14258
|
type: WASM_THREAD_INIT,
|
|
14109
14259
|
pid: opts.shownPid ?? opts.pid,
|
|
@@ -14116,12 +14266,15 @@ function threadInit(opts, program, sab, cred, thread) {
|
|
|
14116
14266
|
cred: copyCred(cred),
|
|
14117
14267
|
owners: opts.owners === true,
|
|
14118
14268
|
...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
|
|
14119
|
-
thread
|
|
14269
|
+
thread,
|
|
14270
|
+
signals: main
|
|
14120
14271
|
};
|
|
14121
14272
|
}
|
|
14122
14273
|
function spawnWasmProcess(opts) {
|
|
14123
14274
|
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
14124
14275
|
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
14276
|
+
if (opts.blocked && opts.program.abi === "wasi")
|
|
14277
|
+
Atomics.store(header3, SAB_I_BLOCKED, opts.blocked);
|
|
14125
14278
|
const threadSignals = /* @__PURE__ */ new Map();
|
|
14126
14279
|
const created3 = new Created();
|
|
14127
14280
|
const process = new WasmProcess(
|
|
@@ -14222,6 +14375,7 @@ function spawnWasmProcess(opts) {
|
|
|
14222
14375
|
const tsab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
14223
14376
|
const tw = opts.createWorker();
|
|
14224
14377
|
const tsignals = threadSignalsOf(tsab);
|
|
14378
|
+
if (thread.blocked) Atomics.store(tsignals.header, SAB_I_BLOCKED, thread.blocked);
|
|
14225
14379
|
threadSignals.set(thread.tid, tsignals);
|
|
14226
14380
|
const tdispatch = (req) => dying.serving(
|
|
14227
14381
|
() => isWasmSyscall(req) ? process.syscall(req, threadCancel(tsignals)) : dispatchSyncFs(req)
|
|
@@ -14243,7 +14397,7 @@ function spawnWasmProcess(opts) {
|
|
|
14243
14397
|
tresponder.dispose();
|
|
14244
14398
|
tw.terminate();
|
|
14245
14399
|
});
|
|
14246
|
-
tw.postMessage(threadInit(opts, program, tsab, process.cred, thread));
|
|
14400
|
+
tw.postMessage(threadInit(opts, program, tsab, process.cred, thread, sab));
|
|
14247
14401
|
};
|
|
14248
14402
|
worker.postMessage(
|
|
14249
14403
|
processInit(opts, sab, process.umask, copyCred(process.cred), lane?.lane),
|
|
@@ -14265,6 +14419,7 @@ function spawnWasmProcess(opts) {
|
|
|
14265
14419
|
onState: (listener) => process.onState(listener),
|
|
14266
14420
|
memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
|
|
14267
14421
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
14422
|
+
blockedSignals: () => opts.program.abi === "wasi" ? Atomics.load(header3, SAB_I_BLOCKED) : 0,
|
|
14268
14423
|
signalMasks: () => process.signalMasks(),
|
|
14269
14424
|
umask: () => process.umask,
|
|
14270
14425
|
cred: () => copyCred(process.cred),
|
|
@@ -17387,15 +17542,25 @@ function shebang(head) {
|
|
|
17387
17542
|
if (head[0] !== 35 || head[1] !== 33) return void 0;
|
|
17388
17543
|
return new TextDecoder().decode(head.subarray(0, SHEBANG_MAX)).slice(2).split("\n")[0].trim().split(/[ \t]+/);
|
|
17389
17544
|
}
|
|
17390
|
-
async function rootOnly(fs, path) {
|
|
17545
|
+
async function rootOnly(fs, path, dir = false) {
|
|
17391
17546
|
const names = chain(path);
|
|
17392
17547
|
for (const [i, at] of names.entries()) {
|
|
17393
17548
|
const st = await fs.lstat(at).catch(() => void 0);
|
|
17394
|
-
const kind = i === names.length - 1 ? st?.isFile : st?.isDirectory;
|
|
17549
|
+
const kind = i === names.length - 1 && !dir ? st?.isFile : st?.isDirectory;
|
|
17395
17550
|
if (!kind || st?.uid !== 0 || (st.mode & 18) !== 0) return false;
|
|
17396
17551
|
}
|
|
17397
17552
|
return true;
|
|
17398
17553
|
}
|
|
17554
|
+
function appendedRoots(given) {
|
|
17555
|
+
const roots = given?.append ?? [];
|
|
17556
|
+
if (!Array.isArray(roots)) throw new TypeError("commands.append must be an array of paths");
|
|
17557
|
+
for (const root of roots) {
|
|
17558
|
+
if (typeof root !== "string" || !root.startsWith("/") || normalizePath(root) !== root) {
|
|
17559
|
+
throw new TypeError(`commands.append: not an absolute, normalised path: ${String(root)}`);
|
|
17560
|
+
}
|
|
17561
|
+
}
|
|
17562
|
+
return [...roots];
|
|
17563
|
+
}
|
|
17399
17564
|
function plainEnv(words2) {
|
|
17400
17565
|
const next2 = words2[1];
|
|
17401
17566
|
if (baseName(words2[0] ?? "") !== "env" || next2 === void 0) return false;
|
|
@@ -17488,6 +17653,8 @@ var Launcher = class {
|
|
|
17488
17653
|
base;
|
|
17489
17654
|
createWorker;
|
|
17490
17655
|
modulesDir;
|
|
17656
|
+
appended;
|
|
17657
|
+
reportedRoots = /* @__PURE__ */ new Set();
|
|
17491
17658
|
env;
|
|
17492
17659
|
catalogs = /* @__PURE__ */ new Map();
|
|
17493
17660
|
ownCatalogs = /* @__PURE__ */ new Map();
|
|
@@ -17594,6 +17761,7 @@ var Launcher = class {
|
|
|
17594
17761
|
this.processMounts = options.processMounts ?? true;
|
|
17595
17762
|
this.pnpmHome = options.env?.PNPM_HOME ?? SYSTEM_PNPM_HOME;
|
|
17596
17763
|
this.modulesDir = options.modules ?? "/node_modules";
|
|
17764
|
+
this.appended = appendedRoots(options.commands);
|
|
17597
17765
|
this.cdp = new CdpHosts(options.cdp);
|
|
17598
17766
|
const hostname = options.hostname ?? DEFAULT_HOSTNAME;
|
|
17599
17767
|
if (!isHostname(hostname)) throw new Error(`not a host name: ${String(hostname)}`);
|
|
@@ -17643,9 +17811,9 @@ var Launcher = class {
|
|
|
17643
17811
|
this.unguardedRoot = options.fs.unguarded?.() ?? options.fs;
|
|
17644
17812
|
this.prefixes = protectedPrefixes(options.protect?.paths ?? []);
|
|
17645
17813
|
this.processFs = this.prefixes.length > 0 ? new ProtectedFs(this.prefixes).view(this.fs) : this.fs;
|
|
17646
|
-
options.fs.protect?.(this.prefixes);
|
|
17647
17814
|
const integrity = options.protect?.integrity;
|
|
17648
17815
|
integrityOptions(integrity);
|
|
17816
|
+
options.fs.protect?.(this.prefixes, Boolean(integrity));
|
|
17649
17817
|
if (integrity && this.prefixes.length > 0) {
|
|
17650
17818
|
this.integrity = new Integrity(
|
|
17651
17819
|
this.prefixes,
|
|
@@ -17668,7 +17836,7 @@ var Launcher = class {
|
|
|
17668
17836
|
});
|
|
17669
17837
|
void this.unlinked.sweep("/");
|
|
17670
17838
|
this.watchers.watch(
|
|
17671
|
-
[this.modulesDir, this.pnpmHome],
|
|
17839
|
+
[this.modulesDir, this.pnpmHome, ...this.appended],
|
|
17672
17840
|
{ recursive: true },
|
|
17673
17841
|
() => this.resetCatalogs()
|
|
17674
17842
|
);
|
|
@@ -17699,7 +17867,10 @@ var Launcher = class {
|
|
|
17699
17867
|
commands(scope = "") {
|
|
17700
17868
|
let found = this.catalogs.get(scope);
|
|
17701
17869
|
if (!found) {
|
|
17702
|
-
found = this.
|
|
17870
|
+
found = this.trustedAppended().then(async (appended) => {
|
|
17871
|
+
const roots = await this.roots(scope, appended);
|
|
17872
|
+
return scanCommands(this.scanned, roots, roots.length - appended.length);
|
|
17873
|
+
}).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
|
|
17703
17874
|
this.catalogs.set(scope, found);
|
|
17704
17875
|
}
|
|
17705
17876
|
return found;
|
|
@@ -17726,10 +17897,37 @@ var Launcher = class {
|
|
|
17726
17897
|
}
|
|
17727
17898
|
return found;
|
|
17728
17899
|
}
|
|
17729
|
-
async roots(scope = "") {
|
|
17730
|
-
const system = [
|
|
17900
|
+
async roots(scope = "", appended) {
|
|
17901
|
+
const system = [
|
|
17902
|
+
this.modulesDir,
|
|
17903
|
+
...await pnpmGlobalRoots(this.base, this.pnpmHome),
|
|
17904
|
+
...appended ?? await this.trustedAppended()
|
|
17905
|
+
];
|
|
17731
17906
|
return scope ? [...await pnpmGlobalRoots(this.base, scope), ...system] : system;
|
|
17732
17907
|
}
|
|
17908
|
+
async rootOnlyPath(root) {
|
|
17909
|
+
for (const at of chain(root)) {
|
|
17910
|
+
const real = await physicalPathAsync(this.base, at);
|
|
17911
|
+
if (!await rootOnly(this.base, real, true)) return false;
|
|
17912
|
+
}
|
|
17913
|
+
return true;
|
|
17914
|
+
}
|
|
17915
|
+
async trustedAppended() {
|
|
17916
|
+
if (this.appended.length === 0 || this.usersMode === "off") return this.appended;
|
|
17917
|
+
const trusted = [];
|
|
17918
|
+
for (const root of this.appended) {
|
|
17919
|
+
const real = await physicalPathAsync(this.base, root);
|
|
17920
|
+
if (await this.rootOnlyPath(root)) trusted.push(root);
|
|
17921
|
+
else if (this.usersMode === "report" && await this.base.exists(real)) {
|
|
17922
|
+
if (!this.reportedRoots.has(root)) {
|
|
17923
|
+
this.reportedRoots.add(root);
|
|
17924
|
+
this.dac?.denied({ pid: 0, uid: 0, op: "commands", path: root, errno: "EACCES" });
|
|
17925
|
+
}
|
|
17926
|
+
trusted.push(root);
|
|
17927
|
+
}
|
|
17928
|
+
}
|
|
17929
|
+
return trusted;
|
|
17930
|
+
}
|
|
17733
17931
|
resetCatalogs() {
|
|
17734
17932
|
this.catalogs.clear();
|
|
17735
17933
|
this.ownCatalogs.clear();
|
|
@@ -17835,14 +18033,22 @@ var Launcher = class {
|
|
|
17835
18033
|
const inner = await this.interpreted(interp, [interp, ...passed], cwd, scope, depth + 1);
|
|
17836
18034
|
const via = [interp, ...inner?.via ?? []];
|
|
17837
18035
|
const sources = [script, ...inner?.sources ?? []];
|
|
17838
|
-
|
|
18036
|
+
const bins = [...command?.bin ? [script] : [], ...inner?.bins ?? []];
|
|
18037
|
+
return inner && {
|
|
18038
|
+
...inner,
|
|
18039
|
+
target: withScriptEnv(inner.target, command),
|
|
18040
|
+
via,
|
|
18041
|
+
sources,
|
|
18042
|
+
...bins.length > 0 ? { bins } : {}
|
|
18043
|
+
};
|
|
17839
18044
|
}
|
|
17840
18045
|
const target = withScriptEnv(found, command);
|
|
17841
18046
|
return {
|
|
17842
18047
|
target,
|
|
17843
18048
|
args: [...target.prefix ?? [], ...passed],
|
|
17844
18049
|
via: [interp],
|
|
17845
|
-
sources: [script]
|
|
18050
|
+
sources: [script],
|
|
18051
|
+
...command?.bin ? { bins: [script] } : {}
|
|
17846
18052
|
};
|
|
17847
18053
|
}
|
|
17848
18054
|
async plan(file, argv, cwd, scope, argv0) {
|
|
@@ -17868,6 +18074,7 @@ var Launcher = class {
|
|
|
17868
18074
|
const want = i < via.length - 1 ? R_OK | X_OK : X_OK;
|
|
17869
18075
|
await need(g, "exec", this.fs.resolvePath(req.cwd, file), want);
|
|
17870
18076
|
}
|
|
18077
|
+
for (const bin of planned?.bins ?? []) await need(g, "exec", bin, R_OK | X_OK);
|
|
17871
18078
|
}
|
|
17872
18079
|
async checkedPlan(req, { ppid, cred, scope }, fds) {
|
|
17873
18080
|
const planned = await this.plan(req.file, req.argv, req.cwd, scope, req.argv0);
|
|
@@ -18166,6 +18373,7 @@ var Launcher = class {
|
|
|
18166
18373
|
},
|
|
18167
18374
|
settling: () => this.settling.isSettling(pid),
|
|
18168
18375
|
...req.ignored ? { ignored: req.ignored } : {},
|
|
18376
|
+
...req.blocked ? { blocked: req.blocked } : {},
|
|
18169
18377
|
...req.umask !== void 0 ? { umask: req.umask } : {},
|
|
18170
18378
|
cred: req.cred,
|
|
18171
18379
|
...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
|
|
@@ -18440,6 +18648,7 @@ var Launcher = class {
|
|
|
18440
18648
|
report,
|
|
18441
18649
|
ppid,
|
|
18442
18650
|
ignored: this.ignoredBy(ppid),
|
|
18651
|
+
blocked: this.blockedBy(ppid),
|
|
18443
18652
|
umask: this.umaskOf(ppid),
|
|
18444
18653
|
cred,
|
|
18445
18654
|
tag: this.tagOf(ppid),
|
|
@@ -18501,6 +18710,7 @@ var Launcher = class {
|
|
|
18501
18710
|
ppid,
|
|
18502
18711
|
fork: state,
|
|
18503
18712
|
ignored: this.ignoredBy(ppid, true),
|
|
18713
|
+
blocked: this.blockedBy(ppid),
|
|
18504
18714
|
umask: this.umaskOf(ppid),
|
|
18505
18715
|
cred: this.credOf(ppid),
|
|
18506
18716
|
tag: this.tagOf(ppid)
|
|
@@ -18552,11 +18762,16 @@ var Launcher = class {
|
|
|
18552
18762
|
}
|
|
18553
18763
|
signalMasksOf(pid) {
|
|
18554
18764
|
const masks = this.processes.get(pid)?.signalMasks?.();
|
|
18555
|
-
|
|
18765
|
+
const blocked = this.blockedBy(pid);
|
|
18766
|
+
const sigBlk = blocked ? { sigBlk: blocked } : {};
|
|
18767
|
+
return masks ? { sigIgn: masks.ignored, sigCgt: masks.caught, ...sigBlk } : sigBlk;
|
|
18556
18768
|
}
|
|
18557
18769
|
controlsJobs(pid) {
|
|
18558
18770
|
return this.settling.isSettling(pid) || (this.ignoredBy(pid) & sigbit(SIG.TTOU)) !== 0;
|
|
18559
18771
|
}
|
|
18772
|
+
blockedBy(pid) {
|
|
18773
|
+
return this.processes.get(pid)?.blockedSignals?.() ?? 0;
|
|
18774
|
+
}
|
|
18560
18775
|
ignoredBy(pid, fork = false) {
|
|
18561
18776
|
return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
|
|
18562
18777
|
}
|
|
@@ -18921,7 +19136,7 @@ var Launcher = class {
|
|
|
18921
19136
|
(dir) => this.userCommandDir(dir),
|
|
18922
19137
|
this.owners
|
|
18923
19138
|
);
|
|
18924
|
-
const nodes = new VfsNodes(fs, (path) => this.released(path));
|
|
19139
|
+
const nodes = new VfsNodes(fs, (path) => this.released(path), this.nodes.entries);
|
|
18925
19140
|
nodes.keepsOnDisk = true;
|
|
18926
19141
|
this.openFiles.add(nodes);
|
|
18927
19142
|
const unlinked = new UnlinkedKeeper(
|
|
@@ -19325,6 +19540,7 @@ function serveKernel(port, deps) {
|
|
|
19325
19540
|
createWorker: deps.createWorker,
|
|
19326
19541
|
...deps.createDriverWorker ? { createDriverWorker: deps.createDriverWorker } : {},
|
|
19327
19542
|
...req.modules ? { modules: req.modules } : {},
|
|
19543
|
+
...req.commands ? { commands: req.commands } : {},
|
|
19328
19544
|
...req.env ? { env: req.env } : {},
|
|
19329
19545
|
...hostOptions(req, port, sealed.hook, clipboard.hook, integrity.lookup),
|
|
19330
19546
|
...req.approve ? { approve: approvals.ask } : {},
|