@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/node.js
CHANGED
|
@@ -3821,14 +3821,14 @@ var Integrity = class {
|
|
|
3821
3821
|
if (!this.root.version) return void 0;
|
|
3822
3822
|
return `${real}\0${await this.root.version(real)}`;
|
|
3823
3823
|
}
|
|
3824
|
-
async read(path, caller,
|
|
3825
|
-
return (await this.readKeyed(path, caller,
|
|
3824
|
+
async read(path, caller, plain3, asked) {
|
|
3825
|
+
return (await this.readKeyed(path, caller, plain3, asked)).bytes;
|
|
3826
3826
|
}
|
|
3827
|
-
async readKeyed(path, caller,
|
|
3827
|
+
async readKeyed(path, caller, plain3, asked) {
|
|
3828
3828
|
const found = await this.real(path, asked);
|
|
3829
|
-
if (found === void 0) return { bytes: await
|
|
3829
|
+
if (found === void 0) return { bytes: await plain3() };
|
|
3830
3830
|
const { real, name: name2 } = found;
|
|
3831
|
-
const read = name2 !== real ? { bytes: await
|
|
3831
|
+
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 };
|
|
3832
3832
|
const { bytes } = read;
|
|
3833
3833
|
const keyed = read.version === void 0 ? { bytes } : { bytes, key: `${real}\0${read.version}` };
|
|
3834
3834
|
await this.verify(name2, bytes, caller, EXEC_OPS);
|
|
@@ -3837,9 +3837,9 @@ var Integrity = class {
|
|
|
3837
3837
|
get readsChecked() {
|
|
3838
3838
|
return this.sources.length > 0;
|
|
3839
3839
|
}
|
|
3840
|
-
async readSource(path, caller,
|
|
3840
|
+
async readSource(path, caller, plain3) {
|
|
3841
3841
|
const found = await this.source(path);
|
|
3842
|
-
return found === void 0 ?
|
|
3842
|
+
return found === void 0 ? plain3() : this.checked(found, caller, plain3);
|
|
3843
3843
|
}
|
|
3844
3844
|
async openSource(path, caller, real) {
|
|
3845
3845
|
const found = await this.source(path, real);
|
|
@@ -3849,10 +3849,10 @@ var Integrity = class {
|
|
|
3849
3849
|
}
|
|
3850
3850
|
await this.checked(found, caller, () => this.root.readFileBuffer(found.real));
|
|
3851
3851
|
}
|
|
3852
|
-
async checked(found, caller,
|
|
3852
|
+
async checked(found, caller, plain3) {
|
|
3853
3853
|
const { real, name: name2 } = found;
|
|
3854
3854
|
if (name2 !== real || !this.root.readVersioned) {
|
|
3855
|
-
const bytes2 = await
|
|
3855
|
+
const bytes2 = await plain3();
|
|
3856
3856
|
await this.verify(name2, bytes2, caller, READ_OPS);
|
|
3857
3857
|
return bytes2;
|
|
3858
3858
|
}
|
|
@@ -3913,8 +3913,8 @@ var Integrity = class {
|
|
|
3913
3913
|
}
|
|
3914
3914
|
}
|
|
3915
3915
|
async expected(path) {
|
|
3916
|
-
const
|
|
3917
|
-
return typeof
|
|
3916
|
+
const answer2 = await this.lookup(path);
|
|
3917
|
+
return typeof answer2 === "string" ? answer2.toLowerCase() : void 0;
|
|
3918
3918
|
}
|
|
3919
3919
|
say(event) {
|
|
3920
3920
|
try {
|
|
@@ -4247,12 +4247,12 @@ var RemoteWatch = class {
|
|
|
4247
4247
|
}
|
|
4248
4248
|
greeted(peer) {
|
|
4249
4249
|
this.arrived(peer);
|
|
4250
|
-
const
|
|
4250
|
+
const answer2 = () => {
|
|
4251
4251
|
this.channel.postMessage({ here: this.tab, to: peer });
|
|
4252
4252
|
if (this.mine.length > 0) void this.announce(this.mine);
|
|
4253
4253
|
};
|
|
4254
|
-
if (this.quiet) void this.quiet().then(
|
|
4255
|
-
else
|
|
4254
|
+
if (this.quiet) void this.quiet().then(answer2, answer2);
|
|
4255
|
+
else answer2();
|
|
4256
4256
|
}
|
|
4257
4257
|
announced({ tab, paths, seq: seq2 }) {
|
|
4258
4258
|
const from = tab;
|
|
@@ -6785,11 +6785,11 @@ function frame(opcode, payload) {
|
|
|
6785
6785
|
return out;
|
|
6786
6786
|
}
|
|
6787
6787
|
function clientFrame(opcode, payload) {
|
|
6788
|
-
const
|
|
6789
|
-
const head =
|
|
6788
|
+
const plain3 = frame(opcode, payload);
|
|
6789
|
+
const head = plain3.length - payload.length;
|
|
6790
6790
|
const mask = crypto.getRandomValues(new Uint8Array(4));
|
|
6791
|
-
const out = new Uint8Array(
|
|
6792
|
-
out.set(
|
|
6791
|
+
const out = new Uint8Array(plain3.length + 4);
|
|
6792
|
+
out.set(plain3.subarray(0, head));
|
|
6793
6793
|
out[1] = out[1] | 128;
|
|
6794
6794
|
out.set(mask, head);
|
|
6795
6795
|
for (let i = 0; i < payload.length; i++) {
|
|
@@ -7392,7 +7392,7 @@ function satisfies(version, range2) {
|
|
|
7392
7392
|
}
|
|
7393
7393
|
|
|
7394
7394
|
// src/version.ts
|
|
7395
|
-
var KERNEL_VERSION = true ? "1.
|
|
7395
|
+
var KERNEL_VERSION = true ? "1.130.0" : "0.0.0-dev";
|
|
7396
7396
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7397
7397
|
function procVersion() {
|
|
7398
7398
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -12391,13 +12391,13 @@ async function chown(entry, path, req) {
|
|
|
12391
12391
|
}
|
|
12392
12392
|
async function runMkdir(entry, path, req) {
|
|
12393
12393
|
const { fs } = entry;
|
|
12394
|
-
const
|
|
12394
|
+
const plain3 = plainDirMode(entry, req.mode);
|
|
12395
12395
|
const parentsMode = !req.exclusive ? plainParentsMode(entry) : void 0;
|
|
12396
12396
|
const fixParents = parentsMode !== void 0 ? await missingParents(fs, path, parentsMode) : void 0;
|
|
12397
|
-
const fresh2 =
|
|
12397
|
+
const fresh2 = plain3 !== void 0 && !await fs.exists(path);
|
|
12398
12398
|
await (req.exclusive ? mkdirExclusive(entry, path, req.mode) : fs.mkdir(path, mkdirOptions(entry, req.mode)));
|
|
12399
12399
|
await fixParents?.();
|
|
12400
|
-
if (fresh2) await fs.chmod(path,
|
|
12400
|
+
if (fresh2) await fs.chmod(path, plain3);
|
|
12401
12401
|
return done;
|
|
12402
12402
|
}
|
|
12403
12403
|
async function shownAs(entry, path, st) {
|
|
@@ -12405,8 +12405,8 @@ async function shownAs(entry, path, st) {
|
|
|
12405
12405
|
return callerStat(guardOf(entry), await real?.catch(() => path) ?? path, st);
|
|
12406
12406
|
}
|
|
12407
12407
|
function readSource(entry, path) {
|
|
12408
|
-
const
|
|
12409
|
-
return entry.source ? entry.source.read(path,
|
|
12408
|
+
const plain3 = () => entry.fs.readFileBuffer(path);
|
|
12409
|
+
return entry.source ? entry.source.read(path, plain3) : plain3();
|
|
12410
12410
|
}
|
|
12411
12411
|
async function run(entry, path, req) {
|
|
12412
12412
|
const { fs, cwd } = entry;
|
|
@@ -16301,11 +16301,11 @@ function carriesUdp(uplink) {
|
|
|
16301
16301
|
return uplink.traits.udp === true && typeof uplink.udp === "function";
|
|
16302
16302
|
}
|
|
16303
16303
|
function answerOf(result) {
|
|
16304
|
-
const
|
|
16305
|
-
const addresses = Array.isArray(
|
|
16304
|
+
const answer2 = Array.isArray(result) ? { addresses: result } : result;
|
|
16305
|
+
const addresses = Array.isArray(answer2?.addresses) ? answer2.addresses.filter((a) => typeof a === "string") : [];
|
|
16306
16306
|
return {
|
|
16307
16307
|
addresses,
|
|
16308
|
-
...typeof
|
|
16308
|
+
...typeof answer2?.ttl === "number" && answer2.ttl >= 0 ? { ttl: answer2.ttl } : {}
|
|
16309
16309
|
};
|
|
16310
16310
|
}
|
|
16311
16311
|
var NEVER = new Routes(true);
|
|
@@ -16383,9 +16383,9 @@ var Resolver = class {
|
|
|
16383
16383
|
async lookup(name2, family, id2, abandoned) {
|
|
16384
16384
|
const uplink = this.uplink;
|
|
16385
16385
|
const timeout = AbortSignal.any([AbortSignal.timeout(this.timeoutMs), abandoned]);
|
|
16386
|
-
let
|
|
16386
|
+
let answer2;
|
|
16387
16387
|
try {
|
|
16388
|
-
|
|
16388
|
+
answer2 = answerOf(
|
|
16389
16389
|
await Promise.race([
|
|
16390
16390
|
uplink.resolve(name2, family, timeout),
|
|
16391
16391
|
new Promise(
|
|
@@ -16396,8 +16396,8 @@ var Resolver = class {
|
|
|
16396
16396
|
} catch {
|
|
16397
16397
|
return [];
|
|
16398
16398
|
}
|
|
16399
|
-
const addresses =
|
|
16400
|
-
if (addresses.length > 0) this.remember(id2, addresses,
|
|
16399
|
+
const addresses = answer2.addresses.filter((a) => this.usable(name2, a, family));
|
|
16400
|
+
if (addresses.length > 0) this.remember(id2, addresses, answer2.ttl);
|
|
16401
16401
|
return addresses;
|
|
16402
16402
|
}
|
|
16403
16403
|
usable(name2, address, family) {
|
|
@@ -18345,6 +18345,95 @@ async function substituteHead(head, ask) {
|
|
|
18345
18345
|
`, values };
|
|
18346
18346
|
}
|
|
18347
18347
|
|
|
18348
|
+
// src/kernel/net/sealed-smtp.ts
|
|
18349
|
+
var SMTP_LINE_MAX = 4096;
|
|
18350
|
+
var GREETING = ["EHLO ", "HELO "];
|
|
18351
|
+
function sniffSmtp(start2) {
|
|
18352
|
+
const upper = start2.toUpperCase();
|
|
18353
|
+
for (const word of GREETING) {
|
|
18354
|
+
if (upper.startsWith(word)) return "yes";
|
|
18355
|
+
if (word.startsWith(upper)) return "more";
|
|
18356
|
+
}
|
|
18357
|
+
return "no";
|
|
18358
|
+
}
|
|
18359
|
+
function decoded(b64) {
|
|
18360
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(b64)) return void 0;
|
|
18361
|
+
try {
|
|
18362
|
+
return atob(b64);
|
|
18363
|
+
} catch {
|
|
18364
|
+
return void 0;
|
|
18365
|
+
}
|
|
18366
|
+
}
|
|
18367
|
+
async function swapped2(text, position, ask) {
|
|
18368
|
+
const placeholders = placeholdersIn(text);
|
|
18369
|
+
if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS) return void 0;
|
|
18370
|
+
const values = usable(await ask(position, placeholders));
|
|
18371
|
+
if (Object.keys(values).length === 0) return void 0;
|
|
18372
|
+
return { text: replaced(text, values), values };
|
|
18373
|
+
}
|
|
18374
|
+
async function plain2(b64, ask) {
|
|
18375
|
+
const text = decoded(b64);
|
|
18376
|
+
const fields = text?.split("\0");
|
|
18377
|
+
if (fields?.length !== 3) return { line: b64 };
|
|
18378
|
+
const [authz, user, pass2] = fields;
|
|
18379
|
+
if (placeholdersIn(authz + user).length > 0) return { line: b64 };
|
|
18380
|
+
const done4 = await swapped2(pass2, "auth-plain", ask);
|
|
18381
|
+
if (!done4) return { line: b64 };
|
|
18382
|
+
return { line: btoa(`${authz}\0${user}\0${done4.text}`), values: done4.values };
|
|
18383
|
+
}
|
|
18384
|
+
async function login(b64, ask) {
|
|
18385
|
+
const text = decoded(b64);
|
|
18386
|
+
const done4 = text === void 0 ? void 0 : await swapped2(text, "auth-login", ask);
|
|
18387
|
+
return done4 ? { line: btoa(done4.text), values: done4.values } : { line: b64 };
|
|
18388
|
+
}
|
|
18389
|
+
var SmtpClient = class {
|
|
18390
|
+
state = "command";
|
|
18391
|
+
ask;
|
|
18392
|
+
constructor(ask) {
|
|
18393
|
+
this.ask = ask;
|
|
18394
|
+
}
|
|
18395
|
+
get done() {
|
|
18396
|
+
return this.state === "done";
|
|
18397
|
+
}
|
|
18398
|
+
async line(text) {
|
|
18399
|
+
const state = this.state;
|
|
18400
|
+
if (state === "done") return { line: text };
|
|
18401
|
+
if (state === "plain" || state === "password") {
|
|
18402
|
+
this.state = "done";
|
|
18403
|
+
if (text === "*") return { line: text };
|
|
18404
|
+
return state === "plain" ? plain2(text, this.ask) : login(text, this.ask);
|
|
18405
|
+
}
|
|
18406
|
+
if (state === "user") {
|
|
18407
|
+
this.state = text === "*" ? "done" : "password";
|
|
18408
|
+
return { line: text };
|
|
18409
|
+
}
|
|
18410
|
+
return this.command(text);
|
|
18411
|
+
}
|
|
18412
|
+
async command(text) {
|
|
18413
|
+
const m = /^AUTH[ \t]+(PLAIN|LOGIN)(?:[ \t]+(\S+))?$/i.exec(text);
|
|
18414
|
+
if (!m) {
|
|
18415
|
+
if (/^(MAIL|RCPT|DATA|BDAT|AUTH)\b/i.test(text)) this.state = "done";
|
|
18416
|
+
return { line: text };
|
|
18417
|
+
}
|
|
18418
|
+
const mech = m[1].toUpperCase();
|
|
18419
|
+
const arg = m[2];
|
|
18420
|
+
if (mech === "LOGIN") {
|
|
18421
|
+
this.state = arg === void 0 ? "user" : "password";
|
|
18422
|
+
return { line: text };
|
|
18423
|
+
}
|
|
18424
|
+
if (arg === void 0) {
|
|
18425
|
+
this.state = "plain";
|
|
18426
|
+
return { line: text };
|
|
18427
|
+
}
|
|
18428
|
+
this.state = "done";
|
|
18429
|
+
const out = await plain2(arg, this.ask);
|
|
18430
|
+
return {
|
|
18431
|
+
line: `${text.slice(0, text.length - arg.length)}${out.line}`,
|
|
18432
|
+
...out.values ? { values: out.values } : {}
|
|
18433
|
+
};
|
|
18434
|
+
}
|
|
18435
|
+
};
|
|
18436
|
+
|
|
18348
18437
|
// src/kernel/net/sealed-conn.ts
|
|
18349
18438
|
var HEAD_IDLE_MS = 2e3;
|
|
18350
18439
|
function substitutes(s) {
|
|
@@ -18376,12 +18465,25 @@ function headEnd2(bytes) {
|
|
|
18376
18465
|
}
|
|
18377
18466
|
return -1;
|
|
18378
18467
|
}
|
|
18379
|
-
|
|
18468
|
+
function modeOf(start2) {
|
|
18469
|
+
const http = sniffHttp1(start2);
|
|
18470
|
+
const smtp = sniffSmtp(start2);
|
|
18471
|
+
if (http === "yes") return "http1";
|
|
18472
|
+
if (smtp === "yes") return "smtp";
|
|
18473
|
+
return http === "no" && smtp === "no" ? "pass" : void 0;
|
|
18474
|
+
}
|
|
18475
|
+
function crlf(bytes) {
|
|
18476
|
+
for (let i = 0; i + 1 < bytes.length; i++) if (bytes[i] === 13 && bytes[i + 1] === 10) return i;
|
|
18477
|
+
return -1;
|
|
18478
|
+
}
|
|
18479
|
+
var SessionWriter = class {
|
|
18380
18480
|
buffer = new Uint8Array(0);
|
|
18381
|
-
|
|
18481
|
+
mode = "sniff";
|
|
18382
18482
|
timer;
|
|
18383
18483
|
chain = Promise.resolve();
|
|
18384
18484
|
failed;
|
|
18485
|
+
session = sessionId();
|
|
18486
|
+
smtp;
|
|
18385
18487
|
conn;
|
|
18386
18488
|
s;
|
|
18387
18489
|
scope;
|
|
@@ -18389,6 +18491,9 @@ var Http1Writer = class {
|
|
|
18389
18491
|
this.conn = conn;
|
|
18390
18492
|
this.s = s;
|
|
18391
18493
|
this.scope = scope;
|
|
18494
|
+
this.smtp = new SmtpClient(
|
|
18495
|
+
(position, placeholders) => this.ask("smtp", position, placeholders)
|
|
18496
|
+
);
|
|
18392
18497
|
}
|
|
18393
18498
|
write(bytes) {
|
|
18394
18499
|
const run2 = this.chain.then(() => this.take(bytes));
|
|
@@ -18398,30 +18503,78 @@ var Http1Writer = class {
|
|
|
18398
18503
|
);
|
|
18399
18504
|
return run2;
|
|
18400
18505
|
}
|
|
18506
|
+
async ask(protocol, position, placeholders, head) {
|
|
18507
|
+
const s = this.s;
|
|
18508
|
+
const values = await s.broker.sessionMaterialize({
|
|
18509
|
+
stamp: await s.stamp(),
|
|
18510
|
+
session: this.session,
|
|
18511
|
+
host: s.host,
|
|
18512
|
+
port: s.port,
|
|
18513
|
+
protocol,
|
|
18514
|
+
position,
|
|
18515
|
+
verified: s.verified,
|
|
18516
|
+
handshakeAt: s.handshakeAt,
|
|
18517
|
+
exit: s.exit,
|
|
18518
|
+
placeholders,
|
|
18519
|
+
...head ? { head } : {}
|
|
18520
|
+
});
|
|
18521
|
+
return values;
|
|
18522
|
+
}
|
|
18523
|
+
remember(values) {
|
|
18524
|
+
this.scope.add(
|
|
18525
|
+
Object.entries(values).map(([placeholder, value2]) => ({ name: "sealed", value: value2, placeholder }))
|
|
18526
|
+
);
|
|
18527
|
+
}
|
|
18401
18528
|
async take(bytes) {
|
|
18402
18529
|
if (this.failed !== void 0) throw this.failed;
|
|
18403
|
-
if (this.
|
|
18530
|
+
if (this.mode === "pass") return this.conn.write(bytes);
|
|
18404
18531
|
clearTimeout(this.timer);
|
|
18405
18532
|
const joined4 = new Uint8Array(this.buffer.length + bytes.length);
|
|
18406
18533
|
joined4.set(this.buffer);
|
|
18407
18534
|
joined4.set(bytes, this.buffer.length);
|
|
18408
18535
|
this.buffer.fill(0);
|
|
18409
18536
|
this.buffer = joined4;
|
|
18410
|
-
|
|
18411
|
-
|
|
18412
|
-
if (
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18537
|
+
if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
|
|
18538
|
+
if (this.mode === "pass") await this.release();
|
|
18539
|
+
else if (this.mode === "http1") await this.http1();
|
|
18540
|
+
else if (this.mode === "smtp") await this.lines();
|
|
18541
|
+
if (this.mode !== "pass" && this.buffer.length > 0)
|
|
18542
|
+
this.timer = setTimeout(() => this.idle(), HEAD_IDLE_MS);
|
|
18416
18543
|
return bytes.length;
|
|
18417
18544
|
}
|
|
18545
|
+
async http1() {
|
|
18546
|
+
const end = headEnd2(this.buffer);
|
|
18547
|
+
if (end > HEAD_MAX || end < 0 && this.buffer.length > HEAD_MAX) await this.release();
|
|
18548
|
+
else if (end >= 0) await this.substitute(end);
|
|
18549
|
+
}
|
|
18550
|
+
async lines() {
|
|
18551
|
+
for (; ; ) {
|
|
18552
|
+
const at = crlf(this.buffer);
|
|
18553
|
+
if (at < 0) break;
|
|
18554
|
+
if (at > SMTP_LINE_MAX) return this.release();
|
|
18555
|
+
const all = this.buffer;
|
|
18556
|
+
this.buffer = all.slice(at + 2);
|
|
18557
|
+
const out = await this.smtp.line(latin12(all.subarray(0, at))).catch(() => ({ line: latin12(all.subarray(0, at)) }));
|
|
18558
|
+
all.fill(0);
|
|
18559
|
+
if ("values" in out && out.values) this.remember(out.values);
|
|
18560
|
+
const line = bytesOf(`${out.line}\r
|
|
18561
|
+
`);
|
|
18562
|
+
try {
|
|
18563
|
+
await writeAll4(this.conn, line);
|
|
18564
|
+
} finally {
|
|
18565
|
+
line.fill(0);
|
|
18566
|
+
}
|
|
18567
|
+
if (this.smtp.done) return this.release();
|
|
18568
|
+
}
|
|
18569
|
+
if (this.buffer.length > SMTP_LINE_MAX) await this.release();
|
|
18570
|
+
}
|
|
18418
18571
|
idle() {
|
|
18419
18572
|
this.chain = this.chain.then(() => this.release()).catch((err) => {
|
|
18420
18573
|
this.failed ??= err;
|
|
18421
18574
|
});
|
|
18422
18575
|
}
|
|
18423
18576
|
async release() {
|
|
18424
|
-
this.
|
|
18577
|
+
this.mode = "pass";
|
|
18425
18578
|
const out = this.buffer;
|
|
18426
18579
|
this.buffer = new Uint8Array(0);
|
|
18427
18580
|
try {
|
|
@@ -18431,37 +18584,15 @@ var Http1Writer = class {
|
|
|
18431
18584
|
}
|
|
18432
18585
|
}
|
|
18433
18586
|
async substitute(end) {
|
|
18434
|
-
this.
|
|
18587
|
+
this.mode = "pass";
|
|
18435
18588
|
const all = this.buffer;
|
|
18436
18589
|
this.buffer = new Uint8Array(0);
|
|
18437
|
-
const s = this.s;
|
|
18438
|
-
const session = sessionId();
|
|
18439
18590
|
const done4 = await substituteHead(
|
|
18440
18591
|
latin12(all.subarray(0, end)),
|
|
18441
|
-
|
|
18442
|
-
stamp: await s.stamp(),
|
|
18443
|
-
session,
|
|
18444
|
-
host: s.host,
|
|
18445
|
-
port: s.port,
|
|
18446
|
-
protocol: "http1",
|
|
18447
|
-
position,
|
|
18448
|
-
verified: s.verified,
|
|
18449
|
-
handshakeAt: s.handshakeAt,
|
|
18450
|
-
exit: s.exit,
|
|
18451
|
-
placeholders,
|
|
18452
|
-
head: head2
|
|
18453
|
-
})
|
|
18592
|
+
(position, placeholders, head2) => this.ask("http1", position, placeholders, head2)
|
|
18454
18593
|
).catch(() => void 0);
|
|
18455
18594
|
const head = done4 ? bytesOf(done4.head) : all.subarray(0, end);
|
|
18456
|
-
if (done4)
|
|
18457
|
-
this.scope.add(
|
|
18458
|
-
Object.entries(done4.values).map(([placeholder, value2]) => ({
|
|
18459
|
-
name: "sealed",
|
|
18460
|
-
value: value2,
|
|
18461
|
-
placeholder
|
|
18462
|
-
}))
|
|
18463
|
-
);
|
|
18464
|
-
}
|
|
18595
|
+
if (done4) this.remember(done4.values);
|
|
18465
18596
|
try {
|
|
18466
18597
|
await writeAll4(this.conn, head);
|
|
18467
18598
|
await writeAll4(this.conn, all.subarray(end));
|
|
@@ -18472,14 +18603,14 @@ var Http1Writer = class {
|
|
|
18472
18603
|
}
|
|
18473
18604
|
flushed() {
|
|
18474
18605
|
clearTimeout(this.timer);
|
|
18475
|
-
this.chain = this.chain.then(() => this.
|
|
18606
|
+
this.chain = this.chain.then(() => this.mode === "pass" ? void 0 : this.release());
|
|
18476
18607
|
return this.chain;
|
|
18477
18608
|
}
|
|
18478
18609
|
drop() {
|
|
18479
18610
|
clearTimeout(this.timer);
|
|
18480
18611
|
this.buffer.fill(0);
|
|
18481
18612
|
this.buffer = new Uint8Array(0);
|
|
18482
|
-
this.
|
|
18613
|
+
this.mode = "pass";
|
|
18483
18614
|
}
|
|
18484
18615
|
};
|
|
18485
18616
|
var IDLE2 = /* @__PURE__ */ Symbol("idle");
|
|
@@ -18490,11 +18621,9 @@ var ScrubReader = class {
|
|
|
18490
18621
|
held = false;
|
|
18491
18622
|
ended = false;
|
|
18492
18623
|
conn;
|
|
18493
|
-
s;
|
|
18494
18624
|
scope;
|
|
18495
|
-
constructor(conn,
|
|
18625
|
+
constructor(conn, scope) {
|
|
18496
18626
|
this.conn = conn;
|
|
18497
|
-
this.s = s;
|
|
18498
18627
|
this.scope = scope;
|
|
18499
18628
|
}
|
|
18500
18629
|
current() {
|
|
@@ -18553,8 +18682,8 @@ function idle() {
|
|
|
18553
18682
|
}
|
|
18554
18683
|
function sealedConn(conn, s) {
|
|
18555
18684
|
const scope = s.broker.sessions.scope(s.pid, s.host);
|
|
18556
|
-
const writer = substitutes(s) ? new
|
|
18557
|
-
const reader = new ScrubReader(conn,
|
|
18685
|
+
const writer = substitutes(s) ? new SessionWriter(conn, s, scope) : void 0;
|
|
18686
|
+
const reader = new ScrubReader(conn, scope);
|
|
18558
18687
|
return {
|
|
18559
18688
|
localAddr: conn.localAddr,
|
|
18560
18689
|
remoteAddr: conn.remoteAddr,
|
|
@@ -19680,6 +19809,12 @@ function tlsOverTransport(req, proc) {
|
|
|
19680
19809
|
return { fd: proc.fds.install(new OpenFile(mine), 3), alpnProtocol: "http/1.1", servername };
|
|
19681
19810
|
}
|
|
19682
19811
|
|
|
19812
|
+
// src/kernel/test-hooks.ts
|
|
19813
|
+
var SYSCALL_HOOK = /* @__PURE__ */ Symbol.for("slicc-kernel.test.syscall");
|
|
19814
|
+
function testSyscallHook() {
|
|
19815
|
+
return globalThis[SYSCALL_HOOK];
|
|
19816
|
+
}
|
|
19817
|
+
|
|
19683
19818
|
// src/kernel/vfs-file.ts
|
|
19684
19819
|
var O_ACCMODE = 3;
|
|
19685
19820
|
var O_WRONLY = 1;
|
|
@@ -20894,7 +21029,8 @@ var WasmProcess = class {
|
|
|
20894
21029
|
cwd,
|
|
20895
21030
|
...moved2,
|
|
20896
21031
|
...group,
|
|
20897
|
-
...exec ? { exec } : {}
|
|
21032
|
+
...exec ? { exec } : {},
|
|
21033
|
+
search: req.search
|
|
20898
21034
|
};
|
|
20899
21035
|
const pid = await this.children.spawn(spawned, stdio, inherit2);
|
|
20900
21036
|
if (deathSignal !== void 0) this.onDeath(pgid === 0 || session ? -pid : pid, deathSignal);
|
|
@@ -20917,8 +21053,8 @@ var WasmProcess = class {
|
|
|
20917
21053
|
spares(sig) {
|
|
20918
21054
|
const { caught, ignored } = this.signalMasks();
|
|
20919
21055
|
const bit = isSignal(sig) ? sigbit(sig) : 0;
|
|
20920
|
-
const
|
|
20921
|
-
return { ok: true, kind: "json", json:
|
|
21056
|
+
const answer2 = (ignored & bit) !== 0 ? "ignore" : (caught & bit) !== 0 ? "spare" : "terminate";
|
|
21057
|
+
return { ok: true, kind: "json", json: answer2 };
|
|
20922
21058
|
}
|
|
20923
21059
|
async killSelf(sig, target, probe2) {
|
|
20924
21060
|
if (!this.options.exitSignal) throw new KernelError("ENOSYS");
|
|
@@ -20980,6 +21116,8 @@ var WasmProcess = class {
|
|
|
20980
21116
|
return void 0;
|
|
20981
21117
|
}
|
|
20982
21118
|
async syscall(req, cancelled, block) {
|
|
21119
|
+
const hook = testSyscallHook();
|
|
21120
|
+
if (hook) await hook({ pid: this.pid, op: req.op });
|
|
20983
21121
|
this.options.onSyscall?.(req);
|
|
20984
21122
|
this.calls += 1;
|
|
20985
21123
|
const started = performance.now();
|
|
@@ -21277,18 +21415,18 @@ var WasmProcess = class {
|
|
|
21277
21415
|
}
|
|
21278
21416
|
if (this.writesAt(req) && this.options.readonlyAt?.(path)) throw new KernelError("EROFS");
|
|
21279
21417
|
const open = { ...req, path };
|
|
21280
|
-
const
|
|
21418
|
+
const plain3 = this.plainMode(req.mode);
|
|
21281
21419
|
if (req.exclusive) {
|
|
21282
21420
|
await nodes.createExclusive(path, this.newOwner(req.mode));
|
|
21283
|
-
if (
|
|
21421
|
+
if (plain3 !== void 0) await fs.chmod?.(path, plain3);
|
|
21284
21422
|
this.fds.installAt(fd, this.openVfsFile(open, void 0, fs));
|
|
21285
21423
|
} else if (req.create) {
|
|
21286
21424
|
await nodes.onEntry(path, async () => {
|
|
21287
|
-
const marks = this.options.owners ||
|
|
21425
|
+
const marks = this.options.owners || plain3 !== void 0;
|
|
21288
21426
|
const fresh2 = marks && !await present3(fs, path, true);
|
|
21289
21427
|
this.fds.installAt(fd, this.openVfsFile(open, await nodes.identify(path), fs));
|
|
21290
21428
|
await this.fds.get(fd).file.stat?.();
|
|
21291
|
-
if (fresh2 &&
|
|
21429
|
+
if (fresh2 && plain3 !== void 0) await fs.chmod?.(path, plain3);
|
|
21292
21430
|
else if (fresh2) {
|
|
21293
21431
|
await fs.chown?.(path, { ...this.newOwner(req.mode), kind: "new" });
|
|
21294
21432
|
}
|
|
@@ -22033,10 +22171,10 @@ var WasmProcess = class {
|
|
|
22033
22171
|
cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
|
|
22034
22172
|
...typeof req.term === "string" ? { term: req.term } : {}
|
|
22035
22173
|
};
|
|
22036
|
-
const
|
|
22037
|
-
if (!("grant" in
|
|
22174
|
+
const answer2 = await sudo(call, this.blockingSignal(cancelled));
|
|
22175
|
+
if (!("grant" in answer2)) return answer2;
|
|
22038
22176
|
if (this.dying) throw new KernelError("EINTR");
|
|
22039
|
-
const { file, argv, env, cwd, cred, caller } =
|
|
22177
|
+
const { file, argv, env, cwd, cred, caller } = answer2.grant;
|
|
22040
22178
|
const stdio = [{ fd: 0 }, { fd: 1 }, { fd: 2 }];
|
|
22041
22179
|
return {
|
|
22042
22180
|
pid: await this.children.spawn({ file, argv, env, cwd, pgid: 0 }, stdio, [], {
|
|
@@ -22196,6 +22334,153 @@ var WASM_THREAD_SPAWN = "wasm-thread-spawn";
|
|
|
22196
22334
|
var WASM_THREAD_INIT = "wasm-thread-init";
|
|
22197
22335
|
var WASM_THREAD_EXIT = "wasm-thread-exit";
|
|
22198
22336
|
var WASM_MAX_THREADS = 256;
|
|
22337
|
+
var JS_THREAD_SPAWN = "js-thread-spawn";
|
|
22338
|
+
var JS_THREAD_INIT = "js-thread-init";
|
|
22339
|
+
var JS_THREAD_EXIT = "js-thread-exit";
|
|
22340
|
+
var JS_MAX_THREADS = 256;
|
|
22341
|
+
var JS_DEFAULT_THREADS = 16;
|
|
22342
|
+
var JS_THREAD_NO_MEMORY = 256;
|
|
22343
|
+
var JS_THREAD_CRASHED = 257;
|
|
22344
|
+
|
|
22345
|
+
// src/kernel/js-threads.ts
|
|
22346
|
+
var JS_OOM = /out of memory|Array buffer allocation failed|Cannot allocate Wasm memory|could not allocate memory|ERR_WORKER_OUT_OF_MEMORY/i;
|
|
22347
|
+
var ENDING = { ok: false, errno: "EINTR", message: "the thread is ending" };
|
|
22348
|
+
var MAIN_ONLY = { ok: true, kind: "void" };
|
|
22349
|
+
function track(ops, req, result) {
|
|
22350
|
+
if (req.op === "async-submit" && result.ok && result.kind === "json") {
|
|
22351
|
+
if (typeof result.json === "number") ops.set(result.json, req.token);
|
|
22352
|
+
} else if (req.op === "async-cancel" || req.op === "async-take" && (result.ok || result.errno !== "EAGAIN")) {
|
|
22353
|
+
ops.delete(req.id);
|
|
22354
|
+
}
|
|
22355
|
+
}
|
|
22356
|
+
function cores() {
|
|
22357
|
+
const n = globalThis.navigator?.hardwareConcurrency;
|
|
22358
|
+
return typeof n === "number" && Number.isInteger(n) && n > 0 ? n : 0;
|
|
22359
|
+
}
|
|
22360
|
+
function jsThreadCap(env) {
|
|
22361
|
+
const asked = Number.parseInt(env.SLICC_JS_THREADS ?? "", 10);
|
|
22362
|
+
if (asked >= 1) return Math.min(asked, JS_MAX_THREADS);
|
|
22363
|
+
return Math.min(JS_MAX_THREADS, Math.max(JS_DEFAULT_THREADS, 2 * cores()));
|
|
22364
|
+
}
|
|
22365
|
+
function codeOf4(code) {
|
|
22366
|
+
if (code === JS_THREAD_NO_MEMORY || code === JS_THREAD_CRASHED) return code;
|
|
22367
|
+
return typeof code === "number" && Number.isInteger(code) ? code & 255 : JS_THREAD_CRASHED;
|
|
22368
|
+
}
|
|
22369
|
+
function answer(control, message3) {
|
|
22370
|
+
control.postMessage(message3);
|
|
22371
|
+
}
|
|
22372
|
+
var JsThreads = class {
|
|
22373
|
+
deps;
|
|
22374
|
+
live = /* @__PURE__ */ new Map();
|
|
22375
|
+
headers = /* @__PURE__ */ new Map();
|
|
22376
|
+
frozen = false;
|
|
22377
|
+
last = 0;
|
|
22378
|
+
closed = false;
|
|
22379
|
+
constructor(deps) {
|
|
22380
|
+
this.deps = deps;
|
|
22381
|
+
}
|
|
22382
|
+
get size() {
|
|
22383
|
+
return this.live.size;
|
|
22384
|
+
}
|
|
22385
|
+
spawn(msg) {
|
|
22386
|
+
const { control, port } = msg;
|
|
22387
|
+
if (this.closed || this.live.size >= this.deps.cap) {
|
|
22388
|
+
answer(
|
|
22389
|
+
control,
|
|
22390
|
+
this.closed ? { errno: "ESRCH", message: "the process is ending" } : { errno: "EAGAIN", message: `more than ${this.deps.cap} threads` }
|
|
22391
|
+
);
|
|
22392
|
+
control.close();
|
|
22393
|
+
port.close();
|
|
22394
|
+
return;
|
|
22395
|
+
}
|
|
22396
|
+
const tid = ++this.last;
|
|
22397
|
+
const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
|
|
22398
|
+
const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
|
|
22399
|
+
if (this.frozen) Atomics.store(header4, SAB_I_STOP, 1);
|
|
22400
|
+
const worker = this.deps.createWorker();
|
|
22401
|
+
const clock = this.deps.clocks.thread(tid + 1, sab);
|
|
22402
|
+
let ended = false;
|
|
22403
|
+
const end = (code) => {
|
|
22404
|
+
if (ended) return;
|
|
22405
|
+
ended = true;
|
|
22406
|
+
this.live.delete(tid);
|
|
22407
|
+
this.headers.delete(tid);
|
|
22408
|
+
this.deps.wakes.delete(header4);
|
|
22409
|
+
for (const [id2, token] of ops) {
|
|
22410
|
+
void this.deps.dispatch({ op: "async-cancel", id: id2, token });
|
|
22411
|
+
}
|
|
22412
|
+
ops.clear();
|
|
22413
|
+
worker.removeEventListener("message", onMessage);
|
|
22414
|
+
worker.removeEventListener("error", onError);
|
|
22415
|
+
control.removeEventListener("message", onControl);
|
|
22416
|
+
responder.dispose();
|
|
22417
|
+
lane.dispose();
|
|
22418
|
+
this.deps.clocks.threadEnded(tid + 1);
|
|
22419
|
+
worker.terminate();
|
|
22420
|
+
answer(control, { exited: code });
|
|
22421
|
+
control.close();
|
|
22422
|
+
};
|
|
22423
|
+
const ops = /* @__PURE__ */ new Map();
|
|
22424
|
+
const dispatch2 = async (req, block) => {
|
|
22425
|
+
if (isWasmSyscall(req) && req.op === "proc-exit") {
|
|
22426
|
+
queueMicrotask(() => end(req.status & 255));
|
|
22427
|
+
return ENDING;
|
|
22428
|
+
}
|
|
22429
|
+
if (isWasmSyscall(req) && req.op === "sig-mask") return MAIN_ONLY;
|
|
22430
|
+
const result = await this.deps.dispatch(req, block);
|
|
22431
|
+
if (!ended) track(ops, req, result);
|
|
22432
|
+
return result;
|
|
22433
|
+
};
|
|
22434
|
+
const responder = this.deps.attach(worker, sab, this.deps.clocks.timed(clock, dispatch2));
|
|
22435
|
+
const lane = this.deps.openLane(dispatch2);
|
|
22436
|
+
const onMessage = (event) => {
|
|
22437
|
+
const data = event.data;
|
|
22438
|
+
if (data?.type === JS_THREAD_EXIT) end(codeOf4(data.code));
|
|
22439
|
+
else if (data?.type === JS_THREAD_SPAWN) this.spawn(event.data);
|
|
22440
|
+
else if (data?.type === WASM_PROCESS_ERROR) this.crashed(String(data.message), end);
|
|
22441
|
+
};
|
|
22442
|
+
const onError = (event) => {
|
|
22443
|
+
event.preventDefault();
|
|
22444
|
+
this.crashed(String(event.message ?? "worker error"), end);
|
|
22445
|
+
};
|
|
22446
|
+
const onControl = (event) => {
|
|
22447
|
+
if (event.data?.terminate === true) end(1);
|
|
22448
|
+
};
|
|
22449
|
+
worker.addEventListener("message", onMessage);
|
|
22450
|
+
worker.addEventListener("error", onError);
|
|
22451
|
+
control.addEventListener("message", onControl);
|
|
22452
|
+
control.start();
|
|
22453
|
+
this.live.set(tid, end);
|
|
22454
|
+
this.headers.set(tid, header4);
|
|
22455
|
+
this.deps.wakes.add(header4);
|
|
22456
|
+
const init = {
|
|
22457
|
+
...this.deps.init(sab, lane.lane),
|
|
22458
|
+
type: JS_THREAD_INIT,
|
|
22459
|
+
thread: { tid, port, data: msg.data }
|
|
22460
|
+
};
|
|
22461
|
+
try {
|
|
22462
|
+
worker.postMessage(init, [lane.lane.port, port, ...msg.transfer ?? []]);
|
|
22463
|
+
} catch {
|
|
22464
|
+
end(JS_THREAD_CRASHED);
|
|
22465
|
+
return;
|
|
22466
|
+
}
|
|
22467
|
+
answer(control, { tid });
|
|
22468
|
+
}
|
|
22469
|
+
crashed(message3, end) {
|
|
22470
|
+
end(JS_OOM.test(message3) ? JS_THREAD_NO_MEMORY : JS_THREAD_CRASHED);
|
|
22471
|
+
}
|
|
22472
|
+
stopped(stopped) {
|
|
22473
|
+
this.frozen = stopped;
|
|
22474
|
+
for (const header4 of this.headers.values()) {
|
|
22475
|
+
Atomics.store(header4, SAB_I_STOP, stopped ? 1 : 0);
|
|
22476
|
+
Atomics.notify(header4, SAB_I_STOP);
|
|
22477
|
+
}
|
|
22478
|
+
}
|
|
22479
|
+
close() {
|
|
22480
|
+
this.closed = true;
|
|
22481
|
+
for (const end of [...this.live.values()]) end(1);
|
|
22482
|
+
}
|
|
22483
|
+
};
|
|
22199
22484
|
|
|
22200
22485
|
// src/kernel/host.ts
|
|
22201
22486
|
var CRASHED = 70;
|
|
@@ -22298,6 +22583,7 @@ function threadSignalsOf(sab) {
|
|
|
22298
22583
|
function threadCancel(thread) {
|
|
22299
22584
|
return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
|
|
22300
22585
|
}
|
|
22586
|
+
var asyncFanout = /* @__PURE__ */ new WeakMap();
|
|
22301
22587
|
function notifiers(header4) {
|
|
22302
22588
|
return {
|
|
22303
22589
|
onPending(sig) {
|
|
@@ -22305,8 +22591,10 @@ function notifiers(header4) {
|
|
|
22305
22591
|
Atomics.notify(header4, SAB_I_SIGNALS);
|
|
22306
22592
|
},
|
|
22307
22593
|
onAsync() {
|
|
22308
|
-
|
|
22309
|
-
|
|
22594
|
+
for (const at of [header4, ...asyncFanout.get(header4) ?? []]) {
|
|
22595
|
+
Atomics.add(at, SAB_I_ASYNC, 1);
|
|
22596
|
+
Atomics.notify(at, SAB_I_ASYNC);
|
|
22597
|
+
}
|
|
22310
22598
|
}
|
|
22311
22599
|
};
|
|
22312
22600
|
}
|
|
@@ -22537,6 +22825,7 @@ function spawnWasmProcess(opts) {
|
|
|
22537
22825
|
dispatch: clocks.timed(void 0, dispatch2)
|
|
22538
22826
|
});
|
|
22539
22827
|
const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
|
|
22828
|
+
const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header4);
|
|
22540
22829
|
const { promise: exited, resolve: settle } = Promise.withResolvers();
|
|
22541
22830
|
let done4 = false;
|
|
22542
22831
|
let endedBy;
|
|
@@ -22550,6 +22839,7 @@ function spawnWasmProcess(opts) {
|
|
|
22550
22839
|
worker.removeEventListener("message", onMessage);
|
|
22551
22840
|
worker.removeEventListener("error", onError);
|
|
22552
22841
|
for (const tid of [...threads.keys()]) endThread(tid);
|
|
22842
|
+
jsThreads?.close();
|
|
22553
22843
|
responder.dispose();
|
|
22554
22844
|
lane?.dispose();
|
|
22555
22845
|
revokeSyncFsToken(token);
|
|
@@ -22573,6 +22863,8 @@ function spawnWasmProcess(opts) {
|
|
|
22573
22863
|
finish(...dying.status(data.code));
|
|
22574
22864
|
} else if (data?.type === WASM_THREAD_SPAWN && data.thread) {
|
|
22575
22865
|
spawnThread(data.thread);
|
|
22866
|
+
} else if (data?.type === JS_THREAD_SPAWN && jsThreads) {
|
|
22867
|
+
jsThreads.spawn(data);
|
|
22576
22868
|
}
|
|
22577
22869
|
};
|
|
22578
22870
|
const onMessage = (event) => handle(event.data);
|
|
@@ -22646,13 +22938,35 @@ function spawnWasmProcess(opts) {
|
|
|
22646
22938
|
termsig: () => endedBy,
|
|
22647
22939
|
onState: (listener) => process2.onState(listener),
|
|
22648
22940
|
memory: () => Atomics.load(header4, SAB_I_MEMORY) * 65536,
|
|
22941
|
+
...processViews(process2, opts, header4),
|
|
22942
|
+
writesBack: () => opts.program.abi === "wasi" && !done4,
|
|
22943
|
+
...clockViews(clocks)
|
|
22944
|
+
};
|
|
22945
|
+
}
|
|
22946
|
+
function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
|
|
22947
|
+
if (opts.program.abi !== "js") return void 0;
|
|
22948
|
+
const wakes = /* @__PURE__ */ new Set();
|
|
22949
|
+
asyncFanout.set(header4, wakes);
|
|
22950
|
+
const threads = new JsThreads({
|
|
22951
|
+
wakes,
|
|
22952
|
+
cap: jsThreadCap(opts.env),
|
|
22953
|
+
createWorker: opts.createWorker,
|
|
22954
|
+
init: (sab, lane) => processInit(opts, sab, process2.umask, copyCred(process2.cred), lane),
|
|
22955
|
+
openLane: (laneDispatch) => openLane(token, laneDispatch),
|
|
22956
|
+
attach: (worker, sab, threadDispatch) => attachSyncSabResponder(worker, sab, token, { dispatch: threadDispatch }),
|
|
22957
|
+
dispatch: dispatch2,
|
|
22958
|
+
clocks
|
|
22959
|
+
});
|
|
22960
|
+
process2.onState((state) => threads.stopped(state === "stopped"));
|
|
22961
|
+
return threads;
|
|
22962
|
+
}
|
|
22963
|
+
function processViews(process2, opts, header4) {
|
|
22964
|
+
return {
|
|
22649
22965
|
ignoredSignals: (fork) => process2.inheritable(fork),
|
|
22650
22966
|
blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header4) : [0, 0],
|
|
22651
22967
|
signalMasks: () => process2.signalMasks(),
|
|
22652
22968
|
umask: () => process2.umask,
|
|
22653
|
-
cred: () => copyCred(process2.cred)
|
|
22654
|
-
writesBack: () => opts.program.abi === "wasi" && !done4,
|
|
22655
|
-
...clockViews(clocks)
|
|
22969
|
+
cred: () => copyCred(process2.cred)
|
|
22656
22970
|
};
|
|
22657
22971
|
}
|
|
22658
22972
|
function clockViews(clocks) {
|
|
@@ -23431,15 +23745,15 @@ function isRecord(value2) {
|
|
|
23431
23745
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23432
23746
|
}
|
|
23433
23747
|
function serialized(reply) {
|
|
23434
|
-
let
|
|
23748
|
+
let plain3;
|
|
23435
23749
|
try {
|
|
23436
23750
|
const text = JSON.stringify(reply);
|
|
23437
|
-
|
|
23751
|
+
plain3 = text === void 0 ? void 0 : JSON.parse(text);
|
|
23438
23752
|
} catch (err) {
|
|
23439
23753
|
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
23440
23754
|
}
|
|
23441
|
-
if (!isRecord(
|
|
23442
|
-
const { v: _, ...rest2 } =
|
|
23755
|
+
if (!isRecord(plain3)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
23756
|
+
const { v: _, ...rest2 } = plain3;
|
|
23443
23757
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
23444
23758
|
}
|
|
23445
23759
|
function lineOf2(err) {
|
|
@@ -23970,8 +24284,8 @@ var FSA_CAPABILITIES = {
|
|
|
23970
24284
|
ranges: true,
|
|
23971
24285
|
sessions: true
|
|
23972
24286
|
};
|
|
23973
|
-
var
|
|
23974
|
-
var denied = (err) =>
|
|
24287
|
+
var codeOf5 = (err) => err?.code;
|
|
24288
|
+
var denied = (err) => codeOf5(err) === "EACCES" || err?.name === "NotAllowedError";
|
|
23975
24289
|
function attrOf(st) {
|
|
23976
24290
|
return {
|
|
23977
24291
|
kind: st.isDirectory ? "directory" : st.isSymbolicLink ? "symlink" : "file",
|
|
@@ -23993,7 +24307,7 @@ function kernelFsHandlers(fs) {
|
|
|
23993
24307
|
try {
|
|
23994
24308
|
return await fs.stat(path);
|
|
23995
24309
|
} catch (err) {
|
|
23996
|
-
if (
|
|
24310
|
+
if (codeOf5(err) === "ENOENT") return void 0;
|
|
23997
24311
|
throw err;
|
|
23998
24312
|
}
|
|
23999
24313
|
}
|
|
@@ -24186,7 +24500,7 @@ function parseFstab(text) {
|
|
|
24186
24500
|
});
|
|
24187
24501
|
return lines2;
|
|
24188
24502
|
}
|
|
24189
|
-
function
|
|
24503
|
+
function codeOf6(err) {
|
|
24190
24504
|
const code = err?.code;
|
|
24191
24505
|
return typeof code === "string" ? code : "EIO";
|
|
24192
24506
|
}
|
|
@@ -24224,18 +24538,18 @@ async function mountLine({ line, spec, invalid }, mount, signal, retries, discar
|
|
|
24224
24538
|
break;
|
|
24225
24539
|
} catch (err) {
|
|
24226
24540
|
failed3 = err;
|
|
24227
|
-
if (FINAL.has(
|
|
24541
|
+
if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
|
|
24228
24542
|
await wait(retries[attempt], signal);
|
|
24229
24543
|
}
|
|
24230
24544
|
}
|
|
24231
|
-
const code =
|
|
24545
|
+
const code = codeOf6(failed3);
|
|
24232
24546
|
return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
|
|
24233
24547
|
}
|
|
24234
24548
|
|
|
24235
24549
|
// src/mount/hostfs.ts
|
|
24236
24550
|
var HOSTFS_IO = 16 * 1024 * 1024;
|
|
24237
|
-
var
|
|
24238
|
-
var unreachable = (err) =>
|
|
24551
|
+
var codeOf7 = (err) => err?.code;
|
|
24552
|
+
var unreachable = (err) => codeOf7(err) === "ENOTCONN";
|
|
24239
24553
|
function rel(path) {
|
|
24240
24554
|
return path.replace(/^\/+/, "");
|
|
24241
24555
|
}
|
|
@@ -24412,7 +24726,7 @@ function hostfsHandlers(current, againMs = RESTORE_AGAIN_MS) {
|
|
|
24412
24726
|
try {
|
|
24413
24727
|
return { opened: await opening2(), restore: void 0 };
|
|
24414
24728
|
} catch (err) {
|
|
24415
|
-
if (!flags2.write ||
|
|
24729
|
+
if (!flags2.write || codeOf7(err) !== "EACCES") throw err;
|
|
24416
24730
|
const was = await client.call("stat", { path: rel(path) });
|
|
24417
24731
|
const mode = was.mode ?? 0;
|
|
24418
24732
|
if (mode & 128) throw err;
|
|
@@ -24837,7 +25151,7 @@ var PortTransport = class {
|
|
|
24837
25151
|
}
|
|
24838
25152
|
};
|
|
24839
25153
|
var errorOf = (err) => ({
|
|
24840
|
-
code: typeof
|
|
25154
|
+
code: typeof codeOf7(err) === "string" ? codeOf7(err) : "EIO",
|
|
24841
25155
|
message: err?.message ?? String(err)
|
|
24842
25156
|
});
|
|
24843
25157
|
function serveHostfsPort(port, transport) {
|
|
@@ -24851,14 +25165,14 @@ function serveHostfsPort(port, transport) {
|
|
|
24851
25165
|
};
|
|
24852
25166
|
const send2 = (reply, transfer = []) => port.postMessage(reply, transfer);
|
|
24853
25167
|
const pending = /* @__PURE__ */ new Set();
|
|
24854
|
-
const
|
|
25168
|
+
const track2 = (work) => {
|
|
24855
25169
|
pending.add(work);
|
|
24856
25170
|
const done4 = () => pending.delete(work);
|
|
24857
25171
|
work.then(done4, done4);
|
|
24858
25172
|
return work;
|
|
24859
25173
|
};
|
|
24860
|
-
const
|
|
24861
|
-
const result = await
|
|
25174
|
+
const answer2 = async (name2, body) => {
|
|
25175
|
+
const result = await track2(transport.call(name2, body));
|
|
24862
25176
|
const opened2 = result?.fh;
|
|
24863
25177
|
if (name2 === "open" && typeof opened2 === "number") handles.add(opened2);
|
|
24864
25178
|
if (name2 === "release") handles.delete(body?.fh);
|
|
@@ -24872,7 +25186,7 @@ function serveHostfsPort(port, transport) {
|
|
|
24872
25186
|
if (op === "ping") return send2({ id: id2, pong: true });
|
|
24873
25187
|
if (op === "bye") return stop();
|
|
24874
25188
|
if (op === "cleanup")
|
|
24875
|
-
return void Promise.allSettled([...pending]).then(() =>
|
|
25189
|
+
return void Promise.allSettled([...pending]).then(() => answer2(data.name, data.body)).catch(() => {
|
|
24876
25190
|
});
|
|
24877
25191
|
if (op === "unwatch") return watches.get(id2)?.abort();
|
|
24878
25192
|
if (op === "watch") {
|
|
@@ -24894,7 +25208,7 @@ function serveHostfsPort(port, transport) {
|
|
|
24894
25208
|
}
|
|
24895
25209
|
try {
|
|
24896
25210
|
if (op === "read") {
|
|
24897
|
-
const read = await
|
|
25211
|
+
const read = await track2(
|
|
24898
25212
|
transport.read(
|
|
24899
25213
|
data.fh,
|
|
24900
25214
|
data.offset,
|
|
@@ -24906,13 +25220,13 @@ function serveHostfsPort(port, transport) {
|
|
|
24906
25220
|
return send2({ id: id2, bytes }, [bytes.buffer]);
|
|
24907
25221
|
}
|
|
24908
25222
|
if (op === "write") {
|
|
24909
|
-
await
|
|
25223
|
+
await track2(
|
|
24910
25224
|
transport.write(data.fh, data.offset, data.bytes)
|
|
24911
25225
|
);
|
|
24912
25226
|
return send2({ id: id2 });
|
|
24913
25227
|
}
|
|
24914
25228
|
if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
|
|
24915
|
-
send2({ id: id2, result: await
|
|
25229
|
+
send2({ id: id2, result: await answer2(data.name, data.body) });
|
|
24916
25230
|
} catch (err) {
|
|
24917
25231
|
send2({ id: id2, error: errorOf(err) });
|
|
24918
25232
|
}
|
|
@@ -25473,13 +25787,13 @@ function splitWords(text) {
|
|
|
25473
25787
|
while (piece.lastIndex < text.length) {
|
|
25474
25788
|
const m = piece.exec(text);
|
|
25475
25789
|
if (!m) return void 0;
|
|
25476
|
-
const [, single, double, escaped,
|
|
25790
|
+
const [, single, double, escaped, plain3, space] = m;
|
|
25477
25791
|
if (space !== void 0) {
|
|
25478
25792
|
if (word !== void 0) words2.push(word);
|
|
25479
25793
|
word = void 0;
|
|
25480
25794
|
continue;
|
|
25481
25795
|
}
|
|
25482
|
-
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ??
|
|
25796
|
+
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain3));
|
|
25483
25797
|
}
|
|
25484
25798
|
if (word !== void 0) words2.push(word);
|
|
25485
25799
|
return words2;
|
|
@@ -25704,14 +26018,14 @@ var Sudo = class {
|
|
|
25704
26018
|
if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
|
|
25705
26019
|
this.pending.add(cred.ruid);
|
|
25706
26020
|
try {
|
|
25707
|
-
const
|
|
25708
|
-
if (typeof
|
|
26021
|
+
const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
|
|
26022
|
+
if (typeof answer2 !== "string") return answer2;
|
|
25709
26023
|
if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
|
|
25710
26024
|
return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
|
|
25711
26025
|
}
|
|
25712
26026
|
const changed = await this.untrusted(path, cwd, word);
|
|
25713
26027
|
if (changed) return changed;
|
|
25714
|
-
if (
|
|
26028
|
+
if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
|
|
25715
26029
|
return failed2("EIO", "sudo: the rule could not be recorded");
|
|
25716
26030
|
}
|
|
25717
26031
|
return grant();
|
|
@@ -25766,11 +26080,11 @@ ${lines2}
|
|
|
25766
26080
|
);
|
|
25767
26081
|
try {
|
|
25768
26082
|
const answered = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
|
|
25769
|
-
const
|
|
25770
|
-
if (
|
|
26083
|
+
const answer2 = await Promise.race([answered, aborted2]);
|
|
26084
|
+
if (answer2 === "aborted" || control.signal.aborted) {
|
|
25771
26085
|
return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
|
|
25772
26086
|
}
|
|
25773
|
-
return
|
|
26087
|
+
return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
|
|
25774
26088
|
} finally {
|
|
25775
26089
|
clearTimeout(timer);
|
|
25776
26090
|
requester.removeEventListener("abort", withdraw);
|
|
@@ -26668,16 +26982,52 @@ var Launcher = class {
|
|
|
26668
26982
|
for (const bin of planned?.bins ?? []) await need(g, "exec", bin, R_OK | X_OK);
|
|
26669
26983
|
if (planned?.target.copy) await need(g, "exec", planned.target.copy, R_OK | X_OK);
|
|
26670
26984
|
}
|
|
26671
|
-
async checkedPlan(req,
|
|
26672
|
-
|
|
26985
|
+
async checkedPlan(req, ctx, fds) {
|
|
26986
|
+
try {
|
|
26987
|
+
return await this.planOrSearch(req, ctx);
|
|
26988
|
+
} catch (err) {
|
|
26673
26989
|
await fds.closeAll();
|
|
26674
|
-
throw err
|
|
26990
|
+
throw err;
|
|
26991
|
+
}
|
|
26992
|
+
}
|
|
26993
|
+
async planOrSearch(req, ctx) {
|
|
26994
|
+
const bare = !req.file.includes("/") && !COMMAND2.test(req.file);
|
|
26995
|
+
try {
|
|
26996
|
+
return await this.planOne(req, ctx);
|
|
26997
|
+
} catch (err) {
|
|
26998
|
+
const code = codeOf8(err);
|
|
26999
|
+
const searched = bare && req.search !== false && (code === "ENOENT" || code === "ENOEXEC");
|
|
27000
|
+
if (!searched || await this.commandAt(req.file, ctx.scope)) throw err;
|
|
27001
|
+
const found = await this.onPath(req, ctx);
|
|
27002
|
+
if (found) return found;
|
|
27003
|
+
throw err;
|
|
27004
|
+
}
|
|
27005
|
+
}
|
|
27006
|
+
async onPath(req, ctx) {
|
|
27007
|
+
const path = req.env.PATH;
|
|
27008
|
+
if (typeof path !== "string") return void 0;
|
|
27009
|
+
let denied2 = false;
|
|
27010
|
+
for (const dir of path.split(":")) {
|
|
27011
|
+
const file = dir === "" ? `./${req.file}` : `${dir.replace(/\/+$/, "")}/${req.file}`;
|
|
27012
|
+
try {
|
|
27013
|
+
return await this.planOne({ ...req, file }, ctx);
|
|
27014
|
+
} catch (err) {
|
|
27015
|
+
const code = codeOf8(err);
|
|
27016
|
+
if (code === "EACCES") denied2 = true;
|
|
27017
|
+
else if (code !== "ENOENT" && code !== "ENOTDIR") throw err;
|
|
27018
|
+
}
|
|
27019
|
+
}
|
|
27020
|
+
if (denied2) throw new SpawnError("EACCES");
|
|
27021
|
+
return void 0;
|
|
27022
|
+
}
|
|
27023
|
+
async planOne(req, { ppid, cred, scope }) {
|
|
27024
|
+
const refused3 = (err) => {
|
|
27025
|
+
throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
|
|
26675
27026
|
};
|
|
26676
27027
|
const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
|
|
26677
27028
|
const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0);
|
|
26678
27029
|
await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
|
|
26679
27030
|
if (planned) return planned;
|
|
26680
|
-
await fds.closeAll();
|
|
26681
27031
|
throw new SpawnError(await this.unrunnable(file, req.cwd, scope));
|
|
26682
27032
|
}
|
|
26683
27033
|
async enterable(g, cwd) {
|
|
@@ -26844,12 +27194,12 @@ var Launcher = class {
|
|
|
26844
27194
|
return `${path}:${st.size}:${st.mtime.getTime()}`;
|
|
26845
27195
|
}
|
|
26846
27196
|
verified(path, caller, fs = this.base) {
|
|
26847
|
-
const
|
|
26848
|
-
return this.integrity ? this.integrity.read(path, caller,
|
|
27197
|
+
const plain3 = () => fs.readFileBuffer(path);
|
|
27198
|
+
return this.integrity ? this.integrity.read(path, caller, plain3) : plain3();
|
|
26849
27199
|
}
|
|
26850
27200
|
keyed(path, caller, asked) {
|
|
26851
|
-
const
|
|
26852
|
-
return this.integrity ? this.integrity.readKeyed(path, caller,
|
|
27201
|
+
const plain3 = async () => this.base.readFileBuffer(path);
|
|
27202
|
+
return this.integrity ? this.integrity.readKeyed(path, caller, plain3, asked) : plain3().then((bytes) => ({ bytes }));
|
|
26853
27203
|
}
|
|
26854
27204
|
cached(cache, key, load) {
|
|
26855
27205
|
const hit = cache.get(key);
|
|
@@ -27046,7 +27396,7 @@ var Launcher = class {
|
|
|
27046
27396
|
});
|
|
27047
27397
|
return {
|
|
27048
27398
|
source: {
|
|
27049
|
-
read: (path,
|
|
27399
|
+
read: (path, plain3) => integrity.readSource(path, caller(), plain3),
|
|
27050
27400
|
open: (path, real) => integrity.openSource(path, caller(), real)
|
|
27051
27401
|
}
|
|
27052
27402
|
};
|
|
@@ -27953,9 +28303,9 @@ var Launcher = class {
|
|
|
27953
28303
|
}
|
|
27954
28304
|
);
|
|
27955
28305
|
}
|
|
27956
|
-
environment(cwd, extra, account,
|
|
28306
|
+
environment(cwd, extra, account, login2 = false) {
|
|
27957
28307
|
const env = {
|
|
27958
|
-
...
|
|
28308
|
+
...login2 ? networkEnv(this.hostname) : this.env,
|
|
27959
28309
|
...userEnv(account, this.pnpmHome),
|
|
27960
28310
|
PWD: cwd,
|
|
27961
28311
|
...extra
|
|
@@ -28182,6 +28532,9 @@ var Launcher = class {
|
|
|
28182
28532
|
function cronLocks() {
|
|
28183
28533
|
return globalThis.navigator?.locks;
|
|
28184
28534
|
}
|
|
28535
|
+
function codeOf8(err) {
|
|
28536
|
+
return err?.code;
|
|
28537
|
+
}
|
|
28185
28538
|
|
|
28186
28539
|
// src/node/loopback.ts
|
|
28187
28540
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -28198,11 +28551,11 @@ function ipv4Place(address) {
|
|
|
28198
28551
|
return void 0;
|
|
28199
28552
|
}
|
|
28200
28553
|
function placeOf(address) {
|
|
28201
|
-
const
|
|
28202
|
-
const kind = isIP3(
|
|
28203
|
-
if (kind === 4) return ipv4Place(
|
|
28554
|
+
const plain3 = address.replace(/^\[(.*)\]$/, "$1").toLowerCase();
|
|
28555
|
+
const kind = isIP3(plain3);
|
|
28556
|
+
if (kind === 4) return ipv4Place(plain3);
|
|
28204
28557
|
if (kind !== 6) return void 0;
|
|
28205
|
-
const words2 = hextets2(
|
|
28558
|
+
const words2 = hextets2(plain3);
|
|
28206
28559
|
const embedded2 = words2.slice(0, 5).every((w) => w === 0) && (words2[5] === 65535 || words2[5] === 0);
|
|
28207
28560
|
if (embedded2 && (words2[5] === 65535 || words2[6] !== 0)) return ipv4Place(ipv4Of(words2));
|
|
28208
28561
|
if (words2.slice(0, 7).every((w) => w === 0) && (words2[7] ?? 0) <= 1) return "loopback";
|
|
@@ -28251,10 +28604,10 @@ function connectRefusal(address, port, place) {
|
|
|
28251
28604
|
return Object.assign(new Error(why), { status: 403, code: "EACCES" });
|
|
28252
28605
|
}
|
|
28253
28606
|
async function addressesOf(host, resolve2) {
|
|
28254
|
-
const
|
|
28255
|
-
if (isIP3(
|
|
28256
|
-
if (loopbackName2(
|
|
28257
|
-
return resolve2(
|
|
28607
|
+
const plain3 = host.replace(/^\[(.*)\]$/, "$1");
|
|
28608
|
+
if (isIP3(plain3)) return [plain3];
|
|
28609
|
+
if (loopbackName2(plain3)) return ["127.0.0.1"];
|
|
28610
|
+
return resolve2(plain3).catch(() => []);
|
|
28258
28611
|
}
|
|
28259
28612
|
async function checkDestination(target, policy, resolve2 = resolveHost) {
|
|
28260
28613
|
const url = new URL(target);
|
|
@@ -28592,7 +28945,7 @@ import { connect as tls } from "node:tls";
|
|
|
28592
28945
|
var PROBE_MS = 3e3;
|
|
28593
28946
|
var PASSED = /* @__PURE__ */ new Set(["ECONNREFUSED", "EHOSTUNREACH", "ENETUNREACH", "ETIMEDOUT", "ECONNRESET"]);
|
|
28594
28947
|
var NO_NAME = /* @__PURE__ */ new Set(["ENOTFOUND", "EAI_AGAIN", "EAI_NONAME", "EAI_FAIL", "ENODATA"]);
|
|
28595
|
-
function
|
|
28948
|
+
function codeOf9(e) {
|
|
28596
28949
|
const code = e?.code;
|
|
28597
28950
|
return typeof code === "string" ? code : void 0;
|
|
28598
28951
|
}
|
|
@@ -28621,7 +28974,7 @@ function probe(secure2, host, port, ms, signal) {
|
|
|
28621
28974
|
signal?.addEventListener("abort", stop, { once: true });
|
|
28622
28975
|
socket.once(secure2 ? "secureConnect" : "connect", () => done4("EPROTO"));
|
|
28623
28976
|
socket.once("error", (e) => {
|
|
28624
|
-
const code =
|
|
28977
|
+
const code = codeOf9(e) ?? "";
|
|
28625
28978
|
done4(PASSED.has(code) ? code : "EPROTO");
|
|
28626
28979
|
});
|
|
28627
28980
|
});
|
|
@@ -28636,7 +28989,7 @@ async function diagnose(url, ms = PROBE_MS, signal) {
|
|
|
28636
28989
|
await abortable(lookup3(host), signal);
|
|
28637
28990
|
} catch (e) {
|
|
28638
28991
|
if (signal?.aborted) throw signal.reason;
|
|
28639
|
-
return NO_NAME.has(
|
|
28992
|
+
return NO_NAME.has(codeOf9(e) ?? "") ? "EAI_NONAME" : void 0;
|
|
28640
28993
|
}
|
|
28641
28994
|
const code = await probe(secure2, host, port, ms, signal);
|
|
28642
28995
|
signal?.throwIfAborted();
|
|
@@ -28655,7 +29008,7 @@ function diagnosing(transport, check = byDefault) {
|
|
|
28655
29008
|
try {
|
|
28656
29009
|
return await open(request);
|
|
28657
29010
|
} catch (e) {
|
|
28658
|
-
if (request.signal.aborted || !(e instanceof Error) ||
|
|
29011
|
+
if (request.signal.aborted || !(e instanceof Error) || codeOf9(e)) throw e;
|
|
28659
29012
|
const code = await abortable(
|
|
28660
29013
|
check(request.url, request.signal).catch(() => void 0),
|
|
28661
29014
|
request.signal
|