@ai-ecoverse/slicc-kernel 1.128.2 → 1.130.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 +27 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +485 -132
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +150 -31
- package/dist/node-process-worker.js.map +4 -4
- package/dist/node.js +493 -140
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +130 -14
- package/dist/process-worker.js.map +4 -4
- package/dist/testing.js +10 -1
- package/dist/testing.js.map +3 -3
- package/dist/types/index.d.ts +1 -0
- package/dist/types/kernel/children.d.ts +1 -0
- package/dist/types/kernel/js-threads.d.ts +38 -0
- package/dist/types/kernel/net/sealed-http1.d.ts +4 -0
- package/dist/types/kernel/net/sealed-smtp.d.ts +15 -0
- package/dist/types/kernel/process.d.ts +1 -0
- package/dist/types/kernel/protocol.d.ts +35 -0
- package/dist/types/kernel/test-hooks.d.ts +7 -0
- package/dist/types/launcher.d.ts +3 -0
- package/dist/types/process/js/js-context.d.ts +3 -0
- package/dist/types/process/js/js-thread.d.ts +22 -0
- package/dist/types/testing.d.ts +1 -0
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -544,14 +544,14 @@ var Integrity = class {
|
|
|
544
544
|
if (!this.root.version) return void 0;
|
|
545
545
|
return `${real}\0${await this.root.version(real)}`;
|
|
546
546
|
}
|
|
547
|
-
async read(path, caller,
|
|
548
|
-
return (await this.readKeyed(path, caller,
|
|
547
|
+
async read(path, caller, plain3, asked) {
|
|
548
|
+
return (await this.readKeyed(path, caller, plain3, asked)).bytes;
|
|
549
549
|
}
|
|
550
|
-
async readKeyed(path, caller,
|
|
550
|
+
async readKeyed(path, caller, plain3, asked) {
|
|
551
551
|
const found = await this.real(path, asked);
|
|
552
|
-
if (found === void 0) return { bytes: await
|
|
552
|
+
if (found === void 0) return { bytes: await plain3() };
|
|
553
553
|
const { real, name: name2 } = found;
|
|
554
|
-
const read = name2 !== real ? { bytes: await
|
|
554
|
+
const read = name2 !== real ? { bytes: await plain3(), version: void 0 } : this.root.readVersioned ? await this.root.readVersioned(real) : { bytes: await this.root.readFileBuffer(real), version: void 0 };
|
|
555
555
|
const { bytes } = read;
|
|
556
556
|
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
557
557
|
await this.verify(name2, bytes, caller, EXEC_OPS);
|
|
@@ -560,9 +560,9 @@ var Integrity = class {
|
|
|
560
560
|
get readsChecked() {
|
|
561
561
|
return this.sources.length > 0;
|
|
562
562
|
}
|
|
563
|
-
async readSource(path, caller,
|
|
563
|
+
async readSource(path, caller, plain3) {
|
|
564
564
|
const found = await this.source(path);
|
|
565
|
-
return found === void 0 ?
|
|
565
|
+
return found === void 0 ? plain3() : this.checked(found, caller, plain3);
|
|
566
566
|
}
|
|
567
567
|
async openSource(path, caller, real) {
|
|
568
568
|
const found = await this.source(path, real);
|
|
@@ -572,10 +572,10 @@ var Integrity = class {
|
|
|
572
572
|
}
|
|
573
573
|
await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
|
|
574
574
|
}
|
|
575
|
-
async checked(found, caller,
|
|
575
|
+
async checked(found, caller, plain3) {
|
|
576
576
|
const { real, name: name2 } = found;
|
|
577
577
|
if (name2 !== real || !this.root.readVersioned) {
|
|
578
|
-
const bytes2 = await
|
|
578
|
+
const bytes2 = await plain3();
|
|
579
579
|
await this.verify(name2, bytes2, caller, READ_OPS);
|
|
580
580
|
return bytes2;
|
|
581
581
|
}
|
|
@@ -636,8 +636,8 @@ var Integrity = class {
|
|
|
636
636
|
}
|
|
637
637
|
}
|
|
638
638
|
async expected(path) {
|
|
639
|
-
const
|
|
640
|
-
return typeof
|
|
639
|
+
const answer2 = await this.lookup(path);
|
|
640
|
+
return typeof answer2 === "string" ? answer2.toLowerCase() : void 0;
|
|
641
641
|
}
|
|
642
642
|
say(event) {
|
|
643
643
|
try {
|
|
@@ -983,12 +983,12 @@ var RemoteWatch = class {
|
|
|
983
983
|
}
|
|
984
984
|
greeted(peer) {
|
|
985
985
|
this.arrived(peer);
|
|
986
|
-
const
|
|
986
|
+
const answer2 = () => {
|
|
987
987
|
this.channel.postMessage({ here: this.tab, to: peer });
|
|
988
988
|
if (this.mine.length > 0) void this.announce(this.mine);
|
|
989
989
|
};
|
|
990
|
-
if (this.quiet) void this.quiet().then(
|
|
991
|
-
else
|
|
990
|
+
if (this.quiet) void this.quiet().then(answer2, answer2);
|
|
991
|
+
else answer2();
|
|
992
992
|
}
|
|
993
993
|
announced({ tab, paths, seq: seq2 }) {
|
|
994
994
|
const from = tab;
|
|
@@ -3232,11 +3232,11 @@ function frame(opcode, payload) {
|
|
|
3232
3232
|
return out;
|
|
3233
3233
|
}
|
|
3234
3234
|
function clientFrame(opcode, payload) {
|
|
3235
|
-
const
|
|
3236
|
-
const head =
|
|
3235
|
+
const plain3 = frame(opcode, payload);
|
|
3236
|
+
const head = plain3.length - payload.length;
|
|
3237
3237
|
const mask = crypto.getRandomValues(new Uint8Array(4));
|
|
3238
|
-
const out = new Uint8Array(
|
|
3239
|
-
out.set(
|
|
3238
|
+
const out = new Uint8Array(plain3.length + 4);
|
|
3239
|
+
out.set(plain3.subarray(0, head));
|
|
3240
3240
|
out[1] = out[1] | 128;
|
|
3241
3241
|
out.set(mask, head);
|
|
3242
3242
|
for (let i = 0; i < payload.length; i++) {
|
|
@@ -7020,7 +7020,7 @@ function satisfies(version, range2) {
|
|
|
7020
7020
|
}
|
|
7021
7021
|
|
|
7022
7022
|
// src/version.ts
|
|
7023
|
-
var KERNEL_VERSION = true ? "1.
|
|
7023
|
+
var KERNEL_VERSION = true ? "1.130.0" : "0.0.0-dev";
|
|
7024
7024
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7025
7025
|
function procVersion() {
|
|
7026
7026
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -12378,13 +12378,13 @@ async function chown(entry, path, req) {
|
|
|
12378
12378
|
}
|
|
12379
12379
|
async function runMkdir(entry, path, req) {
|
|
12380
12380
|
const { fs } = entry;
|
|
12381
|
-
const
|
|
12381
|
+
const plain3 = plainDirMode(entry, req.mode);
|
|
12382
12382
|
const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
|
|
12383
12383
|
const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
|
|
12384
|
-
const fresh2 =
|
|
12384
|
+
const fresh2 = plain3 !== void 0 && !await fs.exists(path);
|
|
12385
12385
|
await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
|
|
12386
12386
|
await fixParents?.();
|
|
12387
|
-
if (fresh2) await fs.chmod(path,
|
|
12387
|
+
if (fresh2) await fs.chmod(path, plain3);
|
|
12388
12388
|
return done2;
|
|
12389
12389
|
}
|
|
12390
12390
|
async function shownAs(entry, path, st) {
|
|
@@ -12392,8 +12392,8 @@ async function shownAs(entry, path, st) {
|
|
|
12392
12392
|
return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
|
|
12393
12393
|
}
|
|
12394
12394
|
function readSource(entry, path) {
|
|
12395
|
-
const
|
|
12396
|
-
return entry.source ? entry.source.read(path,
|
|
12395
|
+
const plain3 = () => entry.fs.readFileBuffer(path);
|
|
12396
|
+
return entry.source ? entry.source.read(path, plain3) : plain3();
|
|
12397
12397
|
}
|
|
12398
12398
|
async function run(entry, path, req) {
|
|
12399
12399
|
const { fs, cwd } = entry;
|
|
@@ -16336,11 +16336,11 @@ function carriesUdp(uplink) {
|
|
|
16336
16336
|
return uplink.traits.udp === true && typeof uplink.udp === "function";
|
|
16337
16337
|
}
|
|
16338
16338
|
function answerOf(result) {
|
|
16339
|
-
const
|
|
16340
|
-
const addresses = Array.isArray(
|
|
16339
|
+
const answer2 = Array.isArray(result) ? { addresses: result } : result;
|
|
16340
|
+
const addresses = Array.isArray(answer2?.addresses) ? answer2.addresses.filter((a) => typeof a === "string") : [];
|
|
16341
16341
|
return {
|
|
16342
16342
|
addresses,
|
|
16343
|
-
...typeof
|
|
16343
|
+
...typeof answer2?.ttl === "number" && answer2.ttl >= 0 ? { ttl: answer2.ttl } : {}
|
|
16344
16344
|
};
|
|
16345
16345
|
}
|
|
16346
16346
|
var NEVER = new Routes(true);
|
|
@@ -16528,9 +16528,9 @@ var Resolver = class {
|
|
|
16528
16528
|
async lookup(name2, family, id2, abandoned) {
|
|
16529
16529
|
const uplink = this.uplink;
|
|
16530
16530
|
const timeout = AbortSignal.any([AbortSignal.timeout(this.timeoutMs), abandoned]);
|
|
16531
|
-
let
|
|
16531
|
+
let answer2;
|
|
16532
16532
|
try {
|
|
16533
|
-
|
|
16533
|
+
answer2 = answerOf(
|
|
16534
16534
|
await Promise.race([
|
|
16535
16535
|
uplink.resolve(name2, family, timeout),
|
|
16536
16536
|
new Promise(
|
|
@@ -16541,8 +16541,8 @@ var Resolver = class {
|
|
|
16541
16541
|
} catch {
|
|
16542
16542
|
return [];
|
|
16543
16543
|
}
|
|
16544
|
-
const addresses =
|
|
16545
|
-
if (addresses.length > 0) this.remember(id2, addresses,
|
|
16544
|
+
const addresses = answer2.addresses.filter((a) => this.usable(name2, a, family));
|
|
16545
|
+
if (addresses.length > 0) this.remember(id2, addresses, answer2.ttl);
|
|
16546
16546
|
return addresses;
|
|
16547
16547
|
}
|
|
16548
16548
|
usable(name2, address, family) {
|
|
@@ -18490,6 +18490,95 @@ async function substituteHead(head, ask) {
|
|
|
18490
18490
|
`, values };
|
|
18491
18491
|
}
|
|
18492
18492
|
|
|
18493
|
+
// src/kernel/net/sealed-smtp.ts
|
|
18494
|
+
var SMTP_LINE_MAX = 4096;
|
|
18495
|
+
var GREETING = ["EHLO ", "HELO "];
|
|
18496
|
+
function sniffSmtp(start2) {
|
|
18497
|
+
const upper = start2.toUpperCase();
|
|
18498
|
+
for (const word of GREETING) {
|
|
18499
|
+
if (upper.startsWith(word)) return "yes";
|
|
18500
|
+
if (word.startsWith(upper)) return "more";
|
|
18501
|
+
}
|
|
18502
|
+
return "no";
|
|
18503
|
+
}
|
|
18504
|
+
function decoded(b64) {
|
|
18505
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(b64)) return void 0;
|
|
18506
|
+
try {
|
|
18507
|
+
return atob(b64);
|
|
18508
|
+
} catch {
|
|
18509
|
+
return void 0;
|
|
18510
|
+
}
|
|
18511
|
+
}
|
|
18512
|
+
async function swapped2(text, position, ask) {
|
|
18513
|
+
const placeholders = placeholdersIn(text);
|
|
18514
|
+
if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS) return void 0;
|
|
18515
|
+
const values = usable(await ask(position, placeholders));
|
|
18516
|
+
if (Object.keys(values).length === 0) return void 0;
|
|
18517
|
+
return { text: replaced(text, values), values };
|
|
18518
|
+
}
|
|
18519
|
+
async function plain2(b64, ask) {
|
|
18520
|
+
const text = decoded(b64);
|
|
18521
|
+
const fields = text?.split("\0");
|
|
18522
|
+
if (fields?.length !== 3) return { line: b64 };
|
|
18523
|
+
const [authz, user, pass2] = fields;
|
|
18524
|
+
if (placeholdersIn(authz + user).length > 0) return { line: b64 };
|
|
18525
|
+
const done5 = await swapped2(pass2, "auth-plain", ask);
|
|
18526
|
+
if (!done5) return { line: b64 };
|
|
18527
|
+
return { line: btoa(`${authz}\0${user}\0${done5.text}`), values: done5.values };
|
|
18528
|
+
}
|
|
18529
|
+
async function login(b64, ask) {
|
|
18530
|
+
const text = decoded(b64);
|
|
18531
|
+
const done5 = text === void 0 ? void 0 : await swapped2(text, "auth-login", ask);
|
|
18532
|
+
return done5 ? { line: btoa(done5.text), values: done5.values } : { line: b64 };
|
|
18533
|
+
}
|
|
18534
|
+
var SmtpClient = class {
|
|
18535
|
+
state = "command";
|
|
18536
|
+
ask;
|
|
18537
|
+
constructor(ask) {
|
|
18538
|
+
this.ask = ask;
|
|
18539
|
+
}
|
|
18540
|
+
get done() {
|
|
18541
|
+
return this.state === "done";
|
|
18542
|
+
}
|
|
18543
|
+
async line(text) {
|
|
18544
|
+
const state = this.state;
|
|
18545
|
+
if (state === "done") return { line: text };
|
|
18546
|
+
if (state === "plain" || state === "password") {
|
|
18547
|
+
this.state = "done";
|
|
18548
|
+
if (text === "*") return { line: text };
|
|
18549
|
+
return state === "plain" ? plain2(text, this.ask) : login(text, this.ask);
|
|
18550
|
+
}
|
|
18551
|
+
if (state === "user") {
|
|
18552
|
+
this.state = text === "*" ? "done" : "password";
|
|
18553
|
+
return { line: text };
|
|
18554
|
+
}
|
|
18555
|
+
return this.command(text);
|
|
18556
|
+
}
|
|
18557
|
+
async command(text) {
|
|
18558
|
+
const m = /^AUTH[ \t]+(PLAIN|LOGIN)(?:[ \t]+(\S+))?$/i.exec(text);
|
|
18559
|
+
if (!m) {
|
|
18560
|
+
if (/^(MAIL|RCPT|DATA|BDAT|AUTH)\b/i.test(text)) this.state = "done";
|
|
18561
|
+
return { line: text };
|
|
18562
|
+
}
|
|
18563
|
+
const mech = m[1].toUpperCase();
|
|
18564
|
+
const arg = m[2];
|
|
18565
|
+
if (mech === "LOGIN") {
|
|
18566
|
+
this.state = arg === void 0 ? "user" : "password";
|
|
18567
|
+
return { line: text };
|
|
18568
|
+
}
|
|
18569
|
+
if (arg === void 0) {
|
|
18570
|
+
this.state = "plain";
|
|
18571
|
+
return { line: text };
|
|
18572
|
+
}
|
|
18573
|
+
this.state = "done";
|
|
18574
|
+
const out = await plain2(arg, this.ask);
|
|
18575
|
+
return {
|
|
18576
|
+
line: `${text.slice(0, text.length - arg.length)}${out.line}`,
|
|
18577
|
+
...out.values ? { values: out.values } : {}
|
|
18578
|
+
};
|
|
18579
|
+
}
|
|
18580
|
+
};
|
|
18581
|
+
|
|
18493
18582
|
// src/kernel/net/sealed-conn.ts
|
|
18494
18583
|
var HEAD_IDLE_MS = 2e3;
|
|
18495
18584
|
function substitutes(s) {
|
|
@@ -18521,12 +18610,25 @@ function headEnd2(bytes) {
|
|
|
18521
18610
|
}
|
|
18522
18611
|
return -1;
|
|
18523
18612
|
}
|
|
18524
|
-
|
|
18613
|
+
function modeOf(start2) {
|
|
18614
|
+
const http = sniffHttp1(start2);
|
|
18615
|
+
const smtp = sniffSmtp(start2);
|
|
18616
|
+
if (http === "yes") return "http1";
|
|
18617
|
+
if (smtp === "yes") return "smtp";
|
|
18618
|
+
return http === "no" && smtp === "no" ? "pass" : void 0;
|
|
18619
|
+
}
|
|
18620
|
+
function crlf(bytes) {
|
|
18621
|
+
for (let i = 0; i + 1 < bytes.length; i++) if (bytes[i] === 13 && bytes[i + 1] === 10) return i;
|
|
18622
|
+
return -1;
|
|
18623
|
+
}
|
|
18624
|
+
var SessionWriter = class {
|
|
18525
18625
|
buffer = new Uint8Array(0);
|
|
18526
|
-
|
|
18626
|
+
mode = "sniff";
|
|
18527
18627
|
timer;
|
|
18528
18628
|
chain = Promise.resolve();
|
|
18529
18629
|
failed;
|
|
18630
|
+
session = sessionId();
|
|
18631
|
+
smtp;
|
|
18530
18632
|
conn;
|
|
18531
18633
|
s;
|
|
18532
18634
|
scope;
|
|
@@ -18534,6 +18636,9 @@ var Http1Writer = class {
|
|
|
18534
18636
|
this.conn = conn;
|
|
18535
18637
|
this.s = s;
|
|
18536
18638
|
this.scope = scope;
|
|
18639
|
+
this.smtp = new SmtpClient(
|
|
18640
|
+
(position, placeholders) => this.ask("smtp", position, placeholders)
|
|
18641
|
+
);
|
|
18537
18642
|
}
|
|
18538
18643
|
write(bytes) {
|
|
18539
18644
|
const run2 = this.chain.then(() => this.take(bytes));
|
|
@@ -18543,30 +18648,78 @@ var Http1Writer = class {
|
|
|
18543
18648
|
);
|
|
18544
18649
|
return run2;
|
|
18545
18650
|
}
|
|
18651
|
+
async ask(protocol, position, placeholders, head) {
|
|
18652
|
+
const s = this.s;
|
|
18653
|
+
const values = await s.broker.sessionMaterialize({
|
|
18654
|
+
stamp: await s.stamp(),
|
|
18655
|
+
session: this.session,
|
|
18656
|
+
host: s.host,
|
|
18657
|
+
port: s.port,
|
|
18658
|
+
protocol,
|
|
18659
|
+
position,
|
|
18660
|
+
verified: s.verified,
|
|
18661
|
+
handshakeAt: s.handshakeAt,
|
|
18662
|
+
exit: s.exit,
|
|
18663
|
+
placeholders,
|
|
18664
|
+
...head ? { head } : {}
|
|
18665
|
+
});
|
|
18666
|
+
return values;
|
|
18667
|
+
}
|
|
18668
|
+
remember(values) {
|
|
18669
|
+
this.scope.add(
|
|
18670
|
+
Object.entries(values).map(([placeholder, value2]) => ({ name: "sealed", value: value2, placeholder }))
|
|
18671
|
+
);
|
|
18672
|
+
}
|
|
18546
18673
|
async take(bytes) {
|
|
18547
18674
|
if (this.failed !== void 0) throw this.failed;
|
|
18548
|
-
if (this.
|
|
18675
|
+
if (this.mode === "pass") return this.conn.write(bytes);
|
|
18549
18676
|
clearTimeout(this.timer);
|
|
18550
18677
|
const joined4 = new Uint8Array(this.buffer.length + bytes.length);
|
|
18551
18678
|
joined4.set(this.buffer);
|
|
18552
18679
|
joined4.set(bytes, this.buffer.length);
|
|
18553
18680
|
this.buffer.fill(0);
|
|
18554
18681
|
this.buffer = joined4;
|
|
18555
|
-
|
|
18556
|
-
|
|
18557
|
-
if (
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18682
|
+
if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
|
|
18683
|
+
if (this.mode === "pass") await this.release();
|
|
18684
|
+
else if (this.mode === "http1") await this.http1();
|
|
18685
|
+
else if (this.mode === "smtp") await this.lines();
|
|
18686
|
+
if (this.mode !== "pass" && this.buffer.length > 0)
|
|
18687
|
+
this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
|
|
18561
18688
|
return bytes.length;
|
|
18562
18689
|
}
|
|
18690
|
+
async http1() {
|
|
18691
|
+
const end = headEnd2(this.buffer);
|
|
18692
|
+
if (end > HEAD_MAX || end < 0 && this.buffer.length > HEAD_MAX) await this.release();
|
|
18693
|
+
else if (end >= 0) await this.substitute(end);
|
|
18694
|
+
}
|
|
18695
|
+
async lines() {
|
|
18696
|
+
for (; ; ) {
|
|
18697
|
+
const at = crlf(this.buffer);
|
|
18698
|
+
if (at < 0) break;
|
|
18699
|
+
if (at > SMTP_LINE_MAX) return this.release();
|
|
18700
|
+
const all = this.buffer;
|
|
18701
|
+
this.buffer = all.slice(at + 2);
|
|
18702
|
+
const out = await this.smtp.line(latin12(all.subarray(0, at))).catch(() => ({ line: latin12(all.subarray(0, at)) }));
|
|
18703
|
+
all.fill(0);
|
|
18704
|
+
if ("values" in out && out.values) this.remember(out.values);
|
|
18705
|
+
const line = bytesOf(`${out.line}\r
|
|
18706
|
+
`);
|
|
18707
|
+
try {
|
|
18708
|
+
await writeAll4(this.conn, line);
|
|
18709
|
+
} finally {
|
|
18710
|
+
line.fill(0);
|
|
18711
|
+
}
|
|
18712
|
+
if (this.smtp.done) return this.release();
|
|
18713
|
+
}
|
|
18714
|
+
if (this.buffer.length > SMTP_LINE_MAX) await this.release();
|
|
18715
|
+
}
|
|
18563
18716
|
idle() {
|
|
18564
18717
|
this.chain = this.chain.then(() => this.release()).catch((err) => {
|
|
18565
18718
|
this.failed ??= err;
|
|
18566
18719
|
});
|
|
18567
18720
|
}
|
|
18568
18721
|
async release() {
|
|
18569
|
-
this.
|
|
18722
|
+
this.mode = "pass";
|
|
18570
18723
|
const out = this.buffer;
|
|
18571
18724
|
this.buffer = new Uint8Array(0);
|
|
18572
18725
|
try {
|
|
@@ -18576,37 +18729,15 @@ var Http1Writer = class {
|
|
|
18576
18729
|
}
|
|
18577
18730
|
}
|
|
18578
18731
|
async substitute(end) {
|
|
18579
|
-
this.
|
|
18732
|
+
this.mode = "pass";
|
|
18580
18733
|
const all = this.buffer;
|
|
18581
18734
|
this.buffer = new Uint8Array(0);
|
|
18582
|
-
const s = this.s;
|
|
18583
|
-
const session = sessionId();
|
|
18584
18735
|
const done5 = await substituteHead(
|
|
18585
18736
|
latin12(all.subarray(0, end)),
|
|
18586
|
-
|
|
18587
|
-
stamp: await s.stamp(),
|
|
18588
|
-
session,
|
|
18589
|
-
host: s.host,
|
|
18590
|
-
port: s.port,
|
|
18591
|
-
protocol: "http1",
|
|
18592
|
-
position,
|
|
18593
|
-
verified: s.verified,
|
|
18594
|
-
handshakeAt: s.handshakeAt,
|
|
18595
|
-
exit: s.exit,
|
|
18596
|
-
placeholders,
|
|
18597
|
-
head: head2
|
|
18598
|
-
})
|
|
18737
|
+
(position, placeholders, head2) => this.ask("http1", position, placeholders, head2)
|
|
18599
18738
|
).catch(() => void 0);
|
|
18600
18739
|
const head = done5 ? bytesOf(done5.head) : all.subarray(0, end);
|
|
18601
|
-
if (done5)
|
|
18602
|
-
this.scope.add(
|
|
18603
|
-
Object.entries(done5.values).map(([placeholder, value2]) => ({
|
|
18604
|
-
name: "sealed",
|
|
18605
|
-
value: value2,
|
|
18606
|
-
placeholder
|
|
18607
|
-
}))
|
|
18608
|
-
);
|
|
18609
|
-
}
|
|
18740
|
+
if (done5) this.remember(done5.values);
|
|
18610
18741
|
try {
|
|
18611
18742
|
await writeAll4(this.conn, head);
|
|
18612
18743
|
await writeAll4(this.conn, all.subarray(end));
|
|
@@ -18617,14 +18748,14 @@ var Http1Writer = class {
|
|
|
18617
18748
|
}
|
|
18618
18749
|
flushed() {
|
|
18619
18750
|
clearTimeout(this.timer);
|
|
18620
|
-
this.chain = this.chain.then(() => this.
|
|
18751
|
+
this.chain = this.chain.then(() => this.mode === "pass" ? void 0 : this.release());
|
|
18621
18752
|
return this.chain;
|
|
18622
18753
|
}
|
|
18623
18754
|
drop() {
|
|
18624
18755
|
clearTimeout(this.timer);
|
|
18625
18756
|
this.buffer.fill(0);
|
|
18626
18757
|
this.buffer = new Uint8Array(0);
|
|
18627
|
-
this.
|
|
18758
|
+
this.mode = "pass";
|
|
18628
18759
|
}
|
|
18629
18760
|
};
|
|
18630
18761
|
var IDLE2 = /* @__PURE__ */ Symbol("idle");
|
|
@@ -18635,11 +18766,9 @@ var ScrubReader = class {
|
|
|
18635
18766
|
held = false;
|
|
18636
18767
|
ended = false;
|
|
18637
18768
|
conn;
|
|
18638
|
-
s;
|
|
18639
18769
|
scope;
|
|
18640
|
-
constructor(conn,
|
|
18770
|
+
constructor(conn, scope) {
|
|
18641
18771
|
this.conn = conn;
|
|
18642
|
-
this.s = s;
|
|
18643
18772
|
this.scope = scope;
|
|
18644
18773
|
}
|
|
18645
18774
|
current() {
|
|
@@ -18698,8 +18827,8 @@ function idle() {
|
|
|
18698
18827
|
}
|
|
18699
18828
|
function sealedConn(conn, s) {
|
|
18700
18829
|
const scope = s.broker.sessions.scope(s.pid, s.host);
|
|
18701
|
-
const writer = substitutes(s) ? new
|
|
18702
|
-
const reader = new ScrubReader(conn,
|
|
18830
|
+
const writer = substitutes(s) ? new SessionWriter(conn, s, scope) : void 0;
|
|
18831
|
+
const reader = new ScrubReader(conn, scope);
|
|
18703
18832
|
return {
|
|
18704
18833
|
localAddr: conn.localAddr,
|
|
18705
18834
|
remoteAddr: conn.remoteAddr,
|
|
@@ -19825,6 +19954,12 @@ function tlsOverTransport(req, proc) {
|
|
|
19825
19954
|
return { fd: proc.fds.install(new OpenFile(mine), 3), alpnProtocol: "http/1.1", servername };
|
|
19826
19955
|
}
|
|
19827
19956
|
|
|
19957
|
+
// src/kernel/test-hooks.ts
|
|
19958
|
+
var SYSCALL_HOOK = /* @__PURE__ */ Symbol.for("slicc-kernel.test.syscall");
|
|
19959
|
+
function testSyscallHook() {
|
|
19960
|
+
return globalThis[SYSCALL_HOOK];
|
|
19961
|
+
}
|
|
19962
|
+
|
|
19828
19963
|
// src/kernel/vfs-file.ts
|
|
19829
19964
|
var O_ACCMODE = 3;
|
|
19830
19965
|
var O_WRONLY = 1;
|
|
@@ -21039,7 +21174,8 @@ var WasmProcess = class {
|
|
|
21039
21174
|
cwd,
|
|
21040
21175
|
...moved2,
|
|
21041
21176
|
...group,
|
|
21042
|
-
...exec ? { exec } : {}
|
|
21177
|
+
...exec ? { exec } : {},
|
|
21178
|
+
search: req.search
|
|
21043
21179
|
};
|
|
21044
21180
|
const pid = await this.children.spawn(spawned, stdio, inherit2);
|
|
21045
21181
|
if (deathSignal !== void 0) this.onDeath(pgid === 0 || session ? -pid : pid, deathSignal);
|
|
@@ -21062,8 +21198,8 @@ var WasmProcess = class {
|
|
|
21062
21198
|
spares(sig) {
|
|
21063
21199
|
const { caught, ignored } = this.signalMasks();
|
|
21064
21200
|
const bit = isSignal(sig) ? sigbit(sig) : 0;
|
|
21065
|
-
const
|
|
21066
|
-
return { ok: true, kind: "json", json:
|
|
21201
|
+
const answer2 = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
|
|
21202
|
+
return { ok: true, kind: "json", json: answer2 };
|
|
21067
21203
|
}
|
|
21068
21204
|
async killSelf(sig, target, probe) {
|
|
21069
21205
|
if (!this.options.exitSignal) throw new KernelError("ENOSYS");
|
|
@@ -21125,6 +21261,8 @@ var WasmProcess = class {
|
|
|
21125
21261
|
return void 0;
|
|
21126
21262
|
}
|
|
21127
21263
|
async syscall(req, cancelled, block) {
|
|
21264
|
+
const hook = testSyscallHook();
|
|
21265
|
+
if (hook) await hook({ pid: this.pid, op: req.op });
|
|
21128
21266
|
this.options.onSyscall?.(req);
|
|
21129
21267
|
this.calls += 1;
|
|
21130
21268
|
const started = performance.now();
|
|
@@ -21422,18 +21560,18 @@ var WasmProcess = class {
|
|
|
21422
21560
|
}
|
|
21423
21561
|
if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
|
|
21424
21562
|
const open2 = { ...req, path };
|
|
21425
|
-
const
|
|
21563
|
+
const plain3 = this.plainMode(req.mode);
|
|
21426
21564
|
if (req.exclusive) {
|
|
21427
21565
|
await nodes.createExclusive(path, this.newOwner(req.mode));
|
|
21428
|
-
if (
|
|
21566
|
+
if (plain3 !== void 0) await fs.chmod?.(path, plain3);
|
|
21429
21567
|
this.fds.installAt(fd, this.openVfsFile(open2, void 0, fs));
|
|
21430
21568
|
} else if (req.create) {
|
|
21431
21569
|
await nodes.onEntry(path, async () => {
|
|
21432
|
-
const marks = this.options.owners ||
|
|
21570
|
+
const marks = this.options.owners || plain3 !== void 0;
|
|
21433
21571
|
const fresh2 = marks && !await present3(fs, path, true);
|
|
21434
21572
|
this.fds.installAt(fd, this.openVfsFile(open2, await nodes.identify(path), fs));
|
|
21435
21573
|
await this.fds.get(fd).file.stat?.();
|
|
21436
|
-
if (fresh2 &&
|
|
21574
|
+
if (fresh2 && plain3 !== void 0) await fs.chmod?.(path, plain3);
|
|
21437
21575
|
else if (fresh2) {
|
|
21438
21576
|
await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
|
|
21439
21577
|
}
|
|
@@ -22178,10 +22316,10 @@ var WasmProcess = class {
|
|
|
22178
22316
|
cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
|
|
22179
22317
|
...typeof req.term === "string" ? { term: req.term } : {}
|
|
22180
22318
|
};
|
|
22181
|
-
const
|
|
22182
|
-
if (!("grant" in
|
|
22319
|
+
const answer2 = await sudo(call, this.blockingSignal(cancelled));
|
|
22320
|
+
if (!("grant" in answer2)) return answer2;
|
|
22183
22321
|
if (this.dying) throw new KernelError("EINTR");
|
|
22184
|
-
const { file, argv, env, cwd, cred, caller } =
|
|
22322
|
+
const { file, argv, env, cwd, cred, caller } = answer2.grant;
|
|
22185
22323
|
const stdio = [{ fd: 0 }, { fd: 1 }, { fd: 2 }];
|
|
22186
22324
|
return {
|
|
22187
22325
|
pid: await this.children.spawn({ file, argv, env, cwd, pgid: 0 }, stdio, [], {
|
|
@@ -22341,6 +22479,153 @@ var WASM_THREAD_SPAWN = "wasm-thread-spawn";
|
|
|
22341
22479
|
var WASM_THREAD_INIT = "wasm-thread-init";
|
|
22342
22480
|
var WASM_THREAD_EXIT = "wasm-thread-exit";
|
|
22343
22481
|
var WASM_MAX_THREADS = 256;
|
|
22482
|
+
var JS_THREAD_SPAWN = "js-thread-spawn";
|
|
22483
|
+
var JS_THREAD_INIT = "js-thread-init";
|
|
22484
|
+
var JS_THREAD_EXIT = "js-thread-exit";
|
|
22485
|
+
var JS_MAX_THREADS = 256;
|
|
22486
|
+
var JS_DEFAULT_THREADS = 16;
|
|
22487
|
+
var JS_THREAD_NO_MEMORY = 256;
|
|
22488
|
+
var JS_THREAD_CRASHED = 257;
|
|
22489
|
+
|
|
22490
|
+
// src/kernel/js-threads.ts
|
|
22491
|
+
var JS_OOM = /out of memory|Array buffer allocation failed|Cannot allocate Wasm memory|could not allocate memory|ERR_WORKER_OUT_OF_MEMORY/i;
|
|
22492
|
+
var ENDING = { ok: false, errno: "EINTR", message: "the thread is ending" };
|
|
22493
|
+
var MAIN_ONLY = { ok: true, kind: "void" };
|
|
22494
|
+
function track(ops, req, result) {
|
|
22495
|
+
if (req.op === "async-submit" && result.ok && result.kind === "json") {
|
|
22496
|
+
if (typeof result.json === "number") ops.set(result.json, req.token);
|
|
22497
|
+
} else if (req.op === "async-cancel" || req.op === "async-take" && (result.ok || result.errno !== "EAGAIN")) {
|
|
22498
|
+
ops.delete(req.id);
|
|
22499
|
+
}
|
|
22500
|
+
}
|
|
22501
|
+
function cores() {
|
|
22502
|
+
const n = globalThis.navigator?.hardwareConcurrency;
|
|
22503
|
+
return typeof n === "number" && Number.isInteger(n) && n > 0 ? n : 0;
|
|
22504
|
+
}
|
|
22505
|
+
function jsThreadCap(env) {
|
|
22506
|
+
const asked = Number.parseInt(env.SLICC_JS_THREADS ?? "", 10);
|
|
22507
|
+
if (asked >= 1) return Math.min(asked, JS_MAX_THREADS);
|
|
22508
|
+
return Math.min(JS_MAX_THREADS, Math.max(JS_DEFAULT_THREADS, 2 * cores()));
|
|
22509
|
+
}
|
|
22510
|
+
function codeOf4(code) {
|
|
22511
|
+
if (code === JS_THREAD_NO_MEMORY || code === JS_THREAD_CRASHED) return code;
|
|
22512
|
+
return typeof code === "number" && Number.isInteger(code) ? code & 255 : JS_THREAD_CRASHED;
|
|
22513
|
+
}
|
|
22514
|
+
function answer(control, message3) {
|
|
22515
|
+
control.postMessage(message3);
|
|
22516
|
+
}
|
|
22517
|
+
var JsThreads = class {
|
|
22518
|
+
deps;
|
|
22519
|
+
live = /* @__PURE__ */ new Map();
|
|
22520
|
+
headers = /* @__PURE__ */ new Map();
|
|
22521
|
+
frozen = false;
|
|
22522
|
+
last = 0;
|
|
22523
|
+
closed = false;
|
|
22524
|
+
constructor(deps) {
|
|
22525
|
+
this.deps = deps;
|
|
22526
|
+
}
|
|
22527
|
+
get size() {
|
|
22528
|
+
return this.live.size;
|
|
22529
|
+
}
|
|
22530
|
+
spawn(msg) {
|
|
22531
|
+
const { control, port } = msg;
|
|
22532
|
+
if (this.closed || this.live.size >= this.deps.cap) {
|
|
22533
|
+
answer(
|
|
22534
|
+
control,
|
|
22535
|
+
this.closed ? { errno: "ESRCH", message: "the process is ending" } : { errno: "EAGAIN", message: `more than ${this.deps.cap} threads` }
|
|
22536
|
+
);
|
|
22537
|
+
control.close();
|
|
22538
|
+
port.close();
|
|
22539
|
+
return;
|
|
22540
|
+
}
|
|
22541
|
+
const tid = ++this.last;
|
|
22542
|
+
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
22543
|
+
const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
22544
|
+
if (this.frozen) Atomics.store(header3, SAB_I_STOP, 1);
|
|
22545
|
+
const worker = this.deps.createWorker();
|
|
22546
|
+
const clock = this.deps.clocks.thread(tid + 1, sab);
|
|
22547
|
+
let ended = false;
|
|
22548
|
+
const end = (code) => {
|
|
22549
|
+
if (ended) return;
|
|
22550
|
+
ended = true;
|
|
22551
|
+
this.live.delete(tid);
|
|
22552
|
+
this.headers.delete(tid);
|
|
22553
|
+
this.deps.wakes.delete(header3);
|
|
22554
|
+
for (const [id2, token] of ops) {
|
|
22555
|
+
void this.deps.dispatch({ op: "async-cancel", id: id2, token });
|
|
22556
|
+
}
|
|
22557
|
+
ops.clear();
|
|
22558
|
+
worker.removeEventListener("message", onMessage);
|
|
22559
|
+
worker.removeEventListener("error", onError);
|
|
22560
|
+
control.removeEventListener("message", onControl);
|
|
22561
|
+
responder.dispose();
|
|
22562
|
+
lane.dispose();
|
|
22563
|
+
this.deps.clocks.threadEnded(tid + 1);
|
|
22564
|
+
worker.terminate();
|
|
22565
|
+
answer(control, { exited: code });
|
|
22566
|
+
control.close();
|
|
22567
|
+
};
|
|
22568
|
+
const ops = /* @__PURE__ */ new Map();
|
|
22569
|
+
const dispatch2 = async (req, block) => {
|
|
22570
|
+
if (isWasmSyscall(req) && req.op === "proc-exit") {
|
|
22571
|
+
queueMicrotask(() => end(req.status & 255));
|
|
22572
|
+
return ENDING;
|
|
22573
|
+
}
|
|
22574
|
+
if (isWasmSyscall(req) && req.op === "sig-mask") return MAIN_ONLY;
|
|
22575
|
+
const result = await this.deps.dispatch(req, block);
|
|
22576
|
+
if (!ended) track(ops, req, result);
|
|
22577
|
+
return result;
|
|
22578
|
+
};
|
|
22579
|
+
const responder = this.deps.attach(worker, sab, this.deps.clocks.timed(clock, dispatch2));
|
|
22580
|
+
const lane = this.deps.openLane(dispatch2);
|
|
22581
|
+
const onMessage = (event) => {
|
|
22582
|
+
const data = event.data;
|
|
22583
|
+
if (data?.type === JS_THREAD_EXIT) end(codeOf4(data.code));
|
|
22584
|
+
else if (data?.type === JS_THREAD_SPAWN) this.spawn(event.data);
|
|
22585
|
+
else if (data?.type === WASM_PROCESS_ERROR) this.crashed(String(data.message), end);
|
|
22586
|
+
};
|
|
22587
|
+
const onError = (event) => {
|
|
22588
|
+
event.preventDefault();
|
|
22589
|
+
this.crashed(String(event.message ?? "worker error"), end);
|
|
22590
|
+
};
|
|
22591
|
+
const onControl = (event) => {
|
|
22592
|
+
if (event.data?.terminate === true) end(1);
|
|
22593
|
+
};
|
|
22594
|
+
worker.addEventListener("message", onMessage);
|
|
22595
|
+
worker.addEventListener("error", onError);
|
|
22596
|
+
control.addEventListener("message", onControl);
|
|
22597
|
+
control.start();
|
|
22598
|
+
this.live.set(tid, end);
|
|
22599
|
+
this.headers.set(tid, header3);
|
|
22600
|
+
this.deps.wakes.add(header3);
|
|
22601
|
+
const init = {
|
|
22602
|
+
...this.deps.init(sab, lane.lane),
|
|
22603
|
+
type: JS_THREAD_INIT,
|
|
22604
|
+
thread: { tid, port, data: msg.data }
|
|
22605
|
+
};
|
|
22606
|
+
try {
|
|
22607
|
+
worker.postMessage(init, [lane.lane.port, port, ...msg.transfer ?? []]);
|
|
22608
|
+
} catch {
|
|
22609
|
+
end(JS_THREAD_CRASHED);
|
|
22610
|
+
return;
|
|
22611
|
+
}
|
|
22612
|
+
answer(control, { tid });
|
|
22613
|
+
}
|
|
22614
|
+
crashed(message3, end) {
|
|
22615
|
+
end(JS_OOM.test(message3) ? JS_THREAD_NO_MEMORY : JS_THREAD_CRASHED);
|
|
22616
|
+
}
|
|
22617
|
+
stopped(stopped) {
|
|
22618
|
+
this.frozen = stopped;
|
|
22619
|
+
for (const header3 of this.headers.values()) {
|
|
22620
|
+
Atomics.store(header3, SAB_I_STOP, stopped ? 1 : 0);
|
|
22621
|
+
Atomics.notify(header3, SAB_I_STOP);
|
|
22622
|
+
}
|
|
22623
|
+
}
|
|
22624
|
+
close() {
|
|
22625
|
+
this.closed = true;
|
|
22626
|
+
for (const end of [...this.live.values()]) end(1);
|
|
22627
|
+
}
|
|
22628
|
+
};
|
|
22344
22629
|
|
|
22345
22630
|
// src/kernel/host.ts
|
|
22346
22631
|
var CRASHED = 70;
|
|
@@ -22443,6 +22728,7 @@ function threadSignalsOf(sab) {
|
|
|
22443
22728
|
function threadCancel(thread) {
|
|
22444
22729
|
return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
22445
22730
|
}
|
|
22731
|
+
var asyncFanout = /* @__PURE__ */ new WeakMap();
|
|
22446
22732
|
function notifiers(header3) {
|
|
22447
22733
|
return {
|
|
22448
22734
|
onPending(sig) {
|
|
@@ -22450,8 +22736,10 @@ function notifiers(header3) {
|
|
|
22450
22736
|
Atomics.notify(header3, SAB_I_SIGNALS);
|
|
22451
22737
|
},
|
|
22452
22738
|
onAsync() {
|
|
22453
|
-
|
|
22454
|
-
|
|
22739
|
+
for (const at of [header3, ...asyncFanout.get(header3) ?? []]) {
|
|
22740
|
+
Atomics.add(at, SAB_I_ASYNC, 1);
|
|
22741
|
+
Atomics.notify(at, SAB_I_ASYNC);
|
|
22742
|
+
}
|
|
22455
22743
|
}
|
|
22456
22744
|
};
|
|
22457
22745
|
}
|
|
@@ -22682,6 +22970,7 @@ function spawnWasmProcess(opts) {
|
|
|
22682
22970
|
dispatch: clocks.timed(void 0, dispatch2)
|
|
22683
22971
|
});
|
|
22684
22972
|
const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
|
|
22973
|
+
const jsThreads = jsThreadsOf(opts, process, token, dispatch2, clocks, header3);
|
|
22685
22974
|
const { promise: exited, resolve: settle3 } = Promise.withResolvers();
|
|
22686
22975
|
let done5 = false;
|
|
22687
22976
|
let endedBy;
|
|
@@ -22695,6 +22984,7 @@ function spawnWasmProcess(opts) {
|
|
|
22695
22984
|
worker.removeEventListener("message", onMessage);
|
|
22696
22985
|
worker.removeEventListener("error", onError);
|
|
22697
22986
|
for (const tid of [...threads.keys()]) endThread(tid);
|
|
22987
|
+
jsThreads?.close();
|
|
22698
22988
|
responder.dispose();
|
|
22699
22989
|
lane?.dispose();
|
|
22700
22990
|
revokeSyncFsToken(token);
|
|
@@ -22718,6 +23008,8 @@ function spawnWasmProcess(opts) {
|
|
|
22718
23008
|
finish(...dying.status(data.code));
|
|
22719
23009
|
} else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
|
|
22720
23010
|
spawnThread(data.thread);
|
|
23011
|
+
} else if (data?.type === JS_THREAD_SPAWN && jsThreads) {
|
|
23012
|
+
jsThreads.spawn(data);
|
|
22721
23013
|
}
|
|
22722
23014
|
};
|
|
22723
23015
|
const onMessage = (event) => handle(event.data);
|
|
@@ -22791,13 +23083,35 @@ function spawnWasmProcess(opts) {
|
|
|
22791
23083
|
termsig: () => endedBy,
|
|
22792
23084
|
onState: (listener) => process.onState(listener),
|
|
22793
23085
|
memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
|
|
23086
|
+
...processViews(process, opts, header3),
|
|
23087
|
+
writesBack: () => opts.program.abi === "wasi" && !done5,
|
|
23088
|
+
...clockViews(clocks)
|
|
23089
|
+
};
|
|
23090
|
+
}
|
|
23091
|
+
function jsThreadsOf(opts, process, token, dispatch2, clocks, header3) {
|
|
23092
|
+
if (opts.program.abi !== "js") return void 0;
|
|
23093
|
+
const wakes = /* @__PURE__ */ new Set();
|
|
23094
|
+
asyncFanout.set(header3, wakes);
|
|
23095
|
+
const threads = new JsThreads({
|
|
23096
|
+
wakes,
|
|
23097
|
+
cap: jsThreadCap(opts.env),
|
|
23098
|
+
createWorker: opts.createWorker,
|
|
23099
|
+
init: (sab, lane) => processInit(opts, sab, process.umask, copyCred(process.cred), lane),
|
|
23100
|
+
openLane: (laneDispatch) => openLane(token, laneDispatch),
|
|
23101
|
+
attach: (worker, sab, threadDispatch) => attachSyncSabResponder(worker, sab, token, { dispatch: threadDispatch }),
|
|
23102
|
+
dispatch: dispatch2,
|
|
23103
|
+
clocks
|
|
23104
|
+
});
|
|
23105
|
+
process.onState((state) => threads.stopped(state === "stopped"));
|
|
23106
|
+
return threads;
|
|
23107
|
+
}
|
|
23108
|
+
function processViews(process, opts, header3) {
|
|
23109
|
+
return {
|
|
22794
23110
|
ignoredSignals: (fork) => process.inheritable(fork),
|
|
22795
23111
|
blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header3) : [0, 0],
|
|
22796
23112
|
signalMasks: () => process.signalMasks(),
|
|
22797
23113
|
umask: () => process.umask,
|
|
22798
|
-
cred: () => copyCred(process.cred)
|
|
22799
|
-
writesBack: () => opts.program.abi === "wasi" && !done5,
|
|
22800
|
-
...clockViews(clocks)
|
|
23114
|
+
cred: () => copyCred(process.cred)
|
|
22801
23115
|
};
|
|
22802
23116
|
}
|
|
22803
23117
|
function clockViews(clocks) {
|
|
@@ -23576,15 +23890,15 @@ function isRecord(value2) {
|
|
|
23576
23890
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23577
23891
|
}
|
|
23578
23892
|
function serialized(reply) {
|
|
23579
|
-
let
|
|
23893
|
+
let plain3;
|
|
23580
23894
|
try {
|
|
23581
23895
|
const text = JSON.stringify(reply);
|
|
23582
|
-
|
|
23896
|
+
plain3 = text === void 0 ? void 0 : JSON.parse(text);
|
|
23583
23897
|
} catch (err) {
|
|
23584
23898
|
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
23585
23899
|
}
|
|
23586
|
-
if (!isRecord(
|
|
23587
|
-
const { v: _, ...rest2 } =
|
|
23900
|
+
if (!isRecord(plain3)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
23901
|
+
const { v: _, ...rest2 } = plain3;
|
|
23588
23902
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
23589
23903
|
}
|
|
23590
23904
|
function lineOf2(err) {
|
|
@@ -24115,8 +24429,8 @@ var FSA_CAPABILITIES = {
|
|
|
24115
24429
|
ranges: true,
|
|
24116
24430
|
sessions: true
|
|
24117
24431
|
};
|
|
24118
|
-
var
|
|
24119
|
-
var denied = (err) =>
|
|
24432
|
+
var codeOf5 = (err) => err?.code;
|
|
24433
|
+
var denied = (err) => codeOf5(err) === "EACCES" || err?.name === "NotAllowedError";
|
|
24120
24434
|
function attrOf(st) {
|
|
24121
24435
|
return {
|
|
24122
24436
|
kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
|
|
@@ -24138,7 +24452,7 @@ function kernelFsHandlers(fs) {
|
|
|
24138
24452
|
try {
|
|
24139
24453
|
return await fs.stat(path);
|
|
24140
24454
|
} catch (err) {
|
|
24141
|
-
if (
|
|
24455
|
+
if (codeOf5(err) === "ENOENT") return void 0;
|
|
24142
24456
|
throw err;
|
|
24143
24457
|
}
|
|
24144
24458
|
}
|
|
@@ -24331,7 +24645,7 @@ function parseFstab(text) {
|
|
|
24331
24645
|
});
|
|
24332
24646
|
return lines2;
|
|
24333
24647
|
}
|
|
24334
|
-
function
|
|
24648
|
+
function codeOf6(err) {
|
|
24335
24649
|
const code = err?.code;
|
|
24336
24650
|
return typeof code === "string" ? code : "EIO";
|
|
24337
24651
|
}
|
|
@@ -24369,18 +24683,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
|
|
|
24369
24683
|
break;
|
|
24370
24684
|
} catch (err) {
|
|
24371
24685
|
failed3 = err;
|
|
24372
|
-
if (FINAL.has(
|
|
24686
|
+
if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
|
|
24373
24687
|
await wait(retries[attempt], signal);
|
|
24374
24688
|
}
|
|
24375
24689
|
}
|
|
24376
|
-
const code =
|
|
24690
|
+
const code = codeOf6(failed3);
|
|
24377
24691
|
return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
|
|
24378
24692
|
}
|
|
24379
24693
|
|
|
24380
24694
|
// src/mount/hostfs.ts
|
|
24381
24695
|
var HOSTFS_IO = 16 * 1024 * 1024;
|
|
24382
|
-
var
|
|
24383
|
-
var unreachable = (err) =>
|
|
24696
|
+
var codeOf7 = (err) => err?.code;
|
|
24697
|
+
var unreachable = (err) => codeOf7(err) === "ENOTCONN";
|
|
24384
24698
|
function rel(path) {
|
|
24385
24699
|
return path.replace(/^\/+/, "");
|
|
24386
24700
|
}
|
|
@@ -24557,7 +24871,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
24557
24871
|
try {
|
|
24558
24872
|
return { opened: await opening2(), restore: void 0 };
|
|
24559
24873
|
} catch (err) {
|
|
24560
|
-
if (!flags2.write ||
|
|
24874
|
+
if (!flags2.write || codeOf7(err) !== "EACCES") throw err;
|
|
24561
24875
|
const was = await client.call("stat", { path: rel(path) });
|
|
24562
24876
|
const mode = was.mode ?? 0;
|
|
24563
24877
|
if (mode & 128) throw err;
|
|
@@ -25546,13 +25860,13 @@ function splitWords(text) {
|
|
|
25546
25860
|
while (piece.lastIndex < text.length) {
|
|
25547
25861
|
const m = piece.exec(text);
|
|
25548
25862
|
if (!m) return void 0;
|
|
25549
|
-
const [, single, double, escaped,
|
|
25863
|
+
const [, single, double, escaped, plain3, space] = m;
|
|
25550
25864
|
if (space !== void 0) {
|
|
25551
25865
|
if (word !== void 0) words2.push(word);
|
|
25552
25866
|
word = void 0;
|
|
25553
25867
|
continue;
|
|
25554
25868
|
}
|
|
25555
|
-
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ??
|
|
25869
|
+
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain3));
|
|
25556
25870
|
}
|
|
25557
25871
|
if (word !== void 0) words2.push(word);
|
|
25558
25872
|
return words2;
|
|
@@ -25777,14 +26091,14 @@ var Sudo = class {
|
|
|
25777
26091
|
if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
|
|
25778
26092
|
this.pending.add(cred.ruid);
|
|
25779
26093
|
try {
|
|
25780
|
-
const
|
|
25781
|
-
if (typeof
|
|
26094
|
+
const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
|
|
26095
|
+
if (typeof answer2 !== "string") return answer2;
|
|
25782
26096
|
if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
|
|
25783
26097
|
return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
|
|
25784
26098
|
}
|
|
25785
26099
|
const changed = await this.untrusted(path, cwd, word);
|
|
25786
26100
|
if (changed) return changed;
|
|
25787
|
-
if (
|
|
26101
|
+
if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
|
|
25788
26102
|
return failed2("EIO", "sudo: the rule could not be recorded");
|
|
25789
26103
|
}
|
|
25790
26104
|
return grant();
|
|
@@ -25839,11 +26153,11 @@ ${lines2}
|
|
|
25839
26153
|
);
|
|
25840
26154
|
try {
|
|
25841
26155
|
const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
25842
|
-
const
|
|
25843
|
-
if (
|
|
26156
|
+
const answer2 = await Promise.race([answered2, aborted2]);
|
|
26157
|
+
if (answer2 === "aborted" || control.signal.aborted) {
|
|
25844
26158
|
return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
|
|
25845
26159
|
}
|
|
25846
|
-
return
|
|
26160
|
+
return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
|
|
25847
26161
|
} finally {
|
|
25848
26162
|
clearTimeout(timer);
|
|
25849
26163
|
requester.removeEventListener("abort", withdraw);
|
|
@@ -26745,16 +27059,52 @@ var Launcher = class {
|
|
|
26745
27059
|
for (const bin of planned?.bins ?? []) await need(g, "exec", bin, R_OK | X_OK);
|
|
26746
27060
|
if (planned?.target.copy) await need(g, "exec", planned.target.copy, R_OK | X_OK);
|
|
26747
27061
|
}
|
|
26748
|
-
async checkedPlan(req,
|
|
26749
|
-
|
|
27062
|
+
async checkedPlan(req, ctx, fds) {
|
|
27063
|
+
try {
|
|
27064
|
+
return await this.planOrSearch(req, ctx);
|
|
27065
|
+
} catch (err) {
|
|
26750
27066
|
await fds.closeAll();
|
|
26751
|
-
throw err
|
|
27067
|
+
throw err;
|
|
27068
|
+
}
|
|
27069
|
+
}
|
|
27070
|
+
async planOrSearch(req, ctx) {
|
|
27071
|
+
const bare = !req.file.includes("/") && !COMMAND2.test(req.file);
|
|
27072
|
+
try {
|
|
27073
|
+
return await this.planOne(req, ctx);
|
|
27074
|
+
} catch (err) {
|
|
27075
|
+
const code = codeOf8(err);
|
|
27076
|
+
const searched = bare && req.search !== false && (code === "ENOENT" || code === "ENOEXEC");
|
|
27077
|
+
if (!searched || await this.commandAt(req.file, ctx.scope)) throw err;
|
|
27078
|
+
const found = await this.onPath(req, ctx);
|
|
27079
|
+
if (found) return found;
|
|
27080
|
+
throw err;
|
|
27081
|
+
}
|
|
27082
|
+
}
|
|
27083
|
+
async onPath(req, ctx) {
|
|
27084
|
+
const path = req.env.PATH;
|
|
27085
|
+
if (typeof path !== "string") return void 0;
|
|
27086
|
+
let denied2 = false;
|
|
27087
|
+
for (const dir of path.split(":")) {
|
|
27088
|
+
const file = dir === "" ? `./${req.file}` : `${dir.replace(/\/+$/, "")}/${req.file}`;
|
|
27089
|
+
try {
|
|
27090
|
+
return await this.planOne({ ...req, file }, ctx);
|
|
27091
|
+
} catch (err) {
|
|
27092
|
+
const code = codeOf8(err);
|
|
27093
|
+
if (code === "EACCES") denied2 = true;
|
|
27094
|
+
else if (code !== "ENOENT" && code !== "ENOTDIR") throw err;
|
|
27095
|
+
}
|
|
27096
|
+
}
|
|
27097
|
+
if (denied2) throw new SpawnError("EACCES");
|
|
27098
|
+
return void 0;
|
|
27099
|
+
}
|
|
27100
|
+
async planOne(req, { ppid, cred, scope }) {
|
|
27101
|
+
const refused3 = (err) => {
|
|
27102
|
+
throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
|
|
26752
27103
|
};
|
|
26753
27104
|
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
|
|
26754
27105
|
const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
|
|
26755
27106
|
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
|
|
26756
27107
|
if (planned) return planned;
|
|
26757
|
-
await fds.closeAll();
|
|
26758
27108
|
throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
|
|
26759
27109
|
}
|
|
26760
27110
|
async enterable(g, cwd) {
|
|
@@ -26921,12 +27271,12 @@ var Launcher = class {
|
|
|
26921
27271
|
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
26922
27272
|
}
|
|
26923
27273
|
verified(path, caller, fs = this.base) {
|
|
26924
|
-
const
|
|
26925
|
-
return this.integrity ? this.integrity.read(path, caller,
|
|
27274
|
+
const plain3 = () => fs.readFileBuffer(path);
|
|
27275
|
+
return this.integrity ? this.integrity.read(path, caller, plain3) : plain3();
|
|
26926
27276
|
}
|
|
26927
27277
|
keyed(path, caller, asked) {
|
|
26928
|
-
const
|
|
26929
|
-
return this.integrity ? this.integrity.readKeyed(path, caller,
|
|
27278
|
+
const plain3 = async () => this.base.readFileBuffer(path);
|
|
27279
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain3, asked) : plain3().then((bytes) => ({ bytes }));
|
|
26930
27280
|
}
|
|
26931
27281
|
cached(cache, key, load) {
|
|
26932
27282
|
const hit = cache.get(key);
|
|
@@ -27123,7 +27473,7 @@ var Launcher = class {
|
|
|
27123
27473
|
});
|
|
27124
27474
|
return {
|
|
27125
27475
|
source: {
|
|
27126
|
-
read: (path,
|
|
27476
|
+
read: (path, plain3) => integrity.readSource(path, caller(), plain3),
|
|
27127
27477
|
open: (path, real) => integrity.openSource(path, caller(), real)
|
|
27128
27478
|
}
|
|
27129
27479
|
};
|
|
@@ -28030,9 +28380,9 @@ var Launcher = class {
|
|
|
28030
28380
|
}
|
|
28031
28381
|
);
|
|
28032
28382
|
}
|
|
28033
|
-
environment(cwd, extra, account,
|
|
28383
|
+
environment(cwd, extra, account, login2 = false) {
|
|
28034
28384
|
const env = {
|
|
28035
|
-
...
|
|
28385
|
+
...login2 ? networkEnv(this.hostname) : this.env,
|
|
28036
28386
|
...userEnv(account, this.pnpmHome),
|
|
28037
28387
|
PWD: cwd,
|
|
28038
28388
|
...extra
|
|
@@ -28259,6 +28609,9 @@ var Launcher = class {
|
|
|
28259
28609
|
function cronLocks() {
|
|
28260
28610
|
return globalThis.navigator?.locks;
|
|
28261
28611
|
}
|
|
28612
|
+
function codeOf8(err) {
|
|
28613
|
+
return err?.code;
|
|
28614
|
+
}
|
|
28262
28615
|
|
|
28263
28616
|
// src/pin.ts
|
|
28264
28617
|
function pinScript(url) {
|
|
@@ -28296,14 +28649,14 @@ function clipboardAsker(port) {
|
|
|
28296
28649
|
await ask("write", stamp, text);
|
|
28297
28650
|
}
|
|
28298
28651
|
};
|
|
28299
|
-
const
|
|
28652
|
+
const answer2 = ({ id: id2, text, error }) => {
|
|
28300
28653
|
const waiting = asks.get(id2);
|
|
28301
28654
|
if (!waiting) return;
|
|
28302
28655
|
asks.delete(id2);
|
|
28303
28656
|
if (error) waiting.reject(Object.assign(new Error(error.message), { name: error.name }));
|
|
28304
28657
|
else waiting.resolve(text);
|
|
28305
28658
|
};
|
|
28306
|
-
return { hook, answer };
|
|
28659
|
+
return { hook, answer: answer2 };
|
|
28307
28660
|
}
|
|
28308
28661
|
|
|
28309
28662
|
// src/integrity-relay.ts
|
|
@@ -28317,14 +28670,14 @@ function integrityAsker(port) {
|
|
|
28317
28670
|
port.postMessage({ integrityAsk: { id: id2, path } });
|
|
28318
28671
|
return waiting.promise;
|
|
28319
28672
|
};
|
|
28320
|
-
const
|
|
28673
|
+
const answer2 = ({ id: id2, hash, error }) => {
|
|
28321
28674
|
const waiting = asks.get(id2);
|
|
28322
28675
|
if (!waiting) return;
|
|
28323
28676
|
asks.delete(id2);
|
|
28324
28677
|
if (error !== void 0) waiting.reject(new Error(error));
|
|
28325
28678
|
else waiting.resolve(hash);
|
|
28326
28679
|
};
|
|
28327
|
-
return { lookup: lookup2, answer };
|
|
28680
|
+
return { lookup: lookup2, answer: answer2 };
|
|
28328
28681
|
}
|
|
28329
28682
|
|
|
28330
28683
|
// src/kernel/net/remote-transport.ts
|
|
@@ -28548,14 +28901,14 @@ function sealedAsker(port) {
|
|
|
28548
28901
|
port.postMessage({ sealedAsk: { id: id2, req } });
|
|
28549
28902
|
return waiting.promise.finally(() => signal.removeEventListener("abort", abort));
|
|
28550
28903
|
};
|
|
28551
|
-
const
|
|
28904
|
+
const answer2 = ({ id: id2, reply, error }) => {
|
|
28552
28905
|
const waiting = asks.get(id2);
|
|
28553
28906
|
if (!waiting) return;
|
|
28554
28907
|
asks.delete(id2);
|
|
28555
28908
|
if (reply) waiting.resolve(reply);
|
|
28556
28909
|
else waiting.reject(new Error(error ?? "no reply"));
|
|
28557
28910
|
};
|
|
28558
|
-
return { hook, answer };
|
|
28911
|
+
return { hook, answer: answer2 };
|
|
28559
28912
|
}
|
|
28560
28913
|
|
|
28561
28914
|
// src/serve.ts
|
|
@@ -28668,8 +29021,8 @@ function sudoApprovals(port) {
|
|
|
28668
29021
|
);
|
|
28669
29022
|
port.postMessage({ sudoAsk: req });
|
|
28670
29023
|
}),
|
|
28671
|
-
answer({ id: id2, answer }) {
|
|
28672
|
-
waiting.get(id2)?.(
|
|
29024
|
+
answer({ id: id2, answer: answer2 }) {
|
|
29025
|
+
waiting.get(id2)?.(answer2);
|
|
28673
29026
|
waiting.delete(id2);
|
|
28674
29027
|
}
|
|
28675
29028
|
};
|
|
@@ -28763,10 +29116,10 @@ function policyAsker(port) {
|
|
|
28763
29116
|
return {
|
|
28764
29117
|
mountPolicy: (policy) => policy === void 0 ? {} : { processMounts: policy === "ask" ? askPolicy : policy },
|
|
28765
29118
|
allowed(data) {
|
|
28766
|
-
const
|
|
28767
|
-
if (!
|
|
28768
|
-
policies.get(
|
|
28769
|
-
policies.delete(
|
|
29119
|
+
const answer2 = data.mountAllowed;
|
|
29120
|
+
if (!answer2) return false;
|
|
29121
|
+
policies.get(answer2.id)?.(answer2.allowed);
|
|
29122
|
+
policies.delete(answer2.id);
|
|
28770
29123
|
return true;
|
|
28771
29124
|
}
|
|
28772
29125
|
};
|