@ai-ecoverse/slicc-kernel 1.125.11 → 1.126.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +161 -21
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +90 -25
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +161 -21
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +90 -25
- package/dist/process-worker.js.map +3 -3
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/kernel/net/tls-client.d.ts +4 -0
- package/dist/types/kernel/net/tls-uplink.d.ts +2 -1
- package/dist/types/kernel/sealed-session.d.ts +44 -0
- package/dist/types/kernel/sealed.d.ts +3 -0
- package/dist/types/kernel/vfs-file.d.ts +1 -0
- package/dist/types/process/js/js-context.d.ts +15 -3
- package/dist/types/process/js/js-io.d.ts +3 -0
- package/dist/types/process/js/js-net.d.ts +1 -0
- package/dist/types/process/js/js-sync.d.ts +5 -3
- package/dist/types/process/js/js-tty.d.ts +11 -1
- package/package.json +2 -2
package/dist/kernel-worker.js
CHANGED
|
@@ -1096,6 +1096,7 @@ var ABSENT_NAMES = 4096;
|
|
|
1096
1096
|
var FILE_HANDLES = 4096;
|
|
1097
1097
|
var STALE = /* @__PURE__ */ new Set(["NotFoundError", "TypeMismatchError"]);
|
|
1098
1098
|
var REPLACED_ATTEMPTS = 4;
|
|
1099
|
+
var RECONCILE_LISTINGS = 8;
|
|
1099
1100
|
var EXECUTABLE = /\/node_modules\/(?:@[^/]+\/)?[^/]+\/bin\//;
|
|
1100
1101
|
var ERRNO_BY_DOM_ERROR = {
|
|
1101
1102
|
NotFoundError: "ENOENT",
|
|
@@ -2455,15 +2456,57 @@ var OpfsFs = class {
|
|
|
2455
2456
|
timesBy: this.id
|
|
2456
2457
|
}));
|
|
2457
2458
|
}
|
|
2459
|
+
async present(paths) {
|
|
2460
|
+
const listed = /* @__PURE__ */ new Map();
|
|
2461
|
+
const done4 = /* @__PURE__ */ new Map();
|
|
2462
|
+
const list = (dir) => {
|
|
2463
|
+
const known = listed.get(dir);
|
|
2464
|
+
if (known !== void 0) return known;
|
|
2465
|
+
const listing = (async () => {
|
|
2466
|
+
const above = dir === "/" ? void 0 : await list(parentOf3(dir));
|
|
2467
|
+
if (above === null) return null;
|
|
2468
|
+
const handle = dir === "/" ? this.root : above?.get(baseOf(dir));
|
|
2469
|
+
if (handle?.kind !== "directory") return void 0;
|
|
2470
|
+
this.calls++;
|
|
2471
|
+
const children3 = /* @__PURE__ */ new Map();
|
|
2472
|
+
try {
|
|
2473
|
+
for await (const child of handle.values())
|
|
2474
|
+
children3.set(child.name, child);
|
|
2475
|
+
} catch {
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2478
|
+
return children3;
|
|
2479
|
+
})().then((children3) => {
|
|
2480
|
+
done4.set(dir, children3);
|
|
2481
|
+
return children3;
|
|
2482
|
+
});
|
|
2483
|
+
listed.set(dir, listing);
|
|
2484
|
+
return listing;
|
|
2485
|
+
};
|
|
2486
|
+
const dirs = [...new Set(paths.filter((p) => split(p).length > 0).map(parentOf3))];
|
|
2487
|
+
let next3 = 0;
|
|
2488
|
+
const lister = async () => {
|
|
2489
|
+
while (next3 < dirs.length) await list(dirs[next3++]);
|
|
2490
|
+
};
|
|
2491
|
+
await Promise.all(Array.from({ length: Math.min(RECONCILE_LISTINGS, dirs.length) }, lister));
|
|
2492
|
+
return async (path) => {
|
|
2493
|
+
if (split(path).length === 0) return true;
|
|
2494
|
+
const listing = done4.get(parentOf3(path));
|
|
2495
|
+
if (listing === null) return this.real(path);
|
|
2496
|
+
return listing?.has(baseOf(path)) === true;
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2458
2499
|
async reconcile() {
|
|
2459
2500
|
if (this.remote && await this.remote.peered()) return 0;
|
|
2460
2501
|
let removed = 0;
|
|
2461
2502
|
const entries = await this.meta.all();
|
|
2462
2503
|
const carried = new Set(entries.filter((e) => !e.vacated).map((e) => e.ino));
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2504
|
+
const checked = entries.filter((e) => !(e.vacated && carried.has(inodeOf(e.path))));
|
|
2505
|
+
const real = await this.present(
|
|
2506
|
+
checked.flatMap((e) => e.link === void 0 ? [e.path] : [e.path, parentOf3(e.path)])
|
|
2507
|
+
);
|
|
2508
|
+
for (const entry of checked) {
|
|
2509
|
+
const stale = entry.link === void 0 ? !await real(entry.path) : await real(entry.path) || !await real(parentOf3(entry.path));
|
|
2467
2510
|
if (!stale) continue;
|
|
2468
2511
|
const seen = JSON.stringify(entry);
|
|
2469
2512
|
await this.meta.update(
|
|
@@ -6656,7 +6699,7 @@ function satisfies(version, range2) {
|
|
|
6656
6699
|
}
|
|
6657
6700
|
|
|
6658
6701
|
// src/version.ts
|
|
6659
|
-
var KERNEL_VERSION = true ? "1.
|
|
6702
|
+
var KERNEL_VERSION = true ? "1.126.0" : "0.0.0-dev";
|
|
6660
6703
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6661
6704
|
function procVersion() {
|
|
6662
6705
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -8288,10 +8331,10 @@ function tunnelRequestUrl(req, origin) {
|
|
|
8288
8331
|
throw new HttpError(400, "malformed request target");
|
|
8289
8332
|
}
|
|
8290
8333
|
const hosts = fieldValues(req.headers, "host");
|
|
8291
|
-
const
|
|
8334
|
+
const hostOk2 = hosts.every(
|
|
8292
8335
|
(h) => URL.canParse(`https://${h}`) && new URL(`https://${h}`).host === base.host
|
|
8293
8336
|
);
|
|
8294
|
-
if (url.origin !== base.origin || !
|
|
8337
|
+
if (url.origin !== base.origin || !hostOk2) {
|
|
8295
8338
|
throw new HttpError(421, `this tunnel is for ${base.host}`);
|
|
8296
8339
|
}
|
|
8297
8340
|
return url.href;
|
|
@@ -17619,6 +17662,10 @@ function controlsOf(o, session, protocol, chain2, shape) {
|
|
|
17619
17662
|
...o.insecure ? insecureOf(session, chain2, shape) : { hostnameMatches: checked || !session.nameMismatch }
|
|
17620
17663
|
};
|
|
17621
17664
|
}
|
|
17665
|
+
function verdictOf(o, session) {
|
|
17666
|
+
if (o.bundled !== true || isIP(o.servername) || session.verifyResult !== 0) return false;
|
|
17667
|
+
return o.checkHostname !== false || !session.nameMismatch;
|
|
17668
|
+
}
|
|
17622
17669
|
async function infoOf(o, session) {
|
|
17623
17670
|
const flags2 = session.verifyResult;
|
|
17624
17671
|
const code = verifyCode(flags2);
|
|
@@ -17631,7 +17678,9 @@ async function infoOf(o, session) {
|
|
|
17631
17678
|
authorized: code === void 0,
|
|
17632
17679
|
...code ? { authorizationError: code, authorizationText: o.engine.verifyInfo(flags2).trim() } : {},
|
|
17633
17680
|
peerCertificates: chain2,
|
|
17634
|
-
...controlsOf(o, session, protocol, chain2, shape)
|
|
17681
|
+
...controlsOf(o, session, protocol, chain2, shape),
|
|
17682
|
+
verified: verdictOf(o, session),
|
|
17683
|
+
handshakeAt: Date.now()
|
|
17635
17684
|
};
|
|
17636
17685
|
}
|
|
17637
17686
|
var FATAL_ALERT = -30592;
|
|
@@ -17749,6 +17798,7 @@ function sessionOf(info, servername) {
|
|
|
17749
17798
|
return {
|
|
17750
17799
|
path: "kernel",
|
|
17751
17800
|
substitutes: false,
|
|
17801
|
+
verified: info.verified,
|
|
17752
17802
|
protocol: info.protocol,
|
|
17753
17803
|
alpnProtocol: info.alpnProtocol,
|
|
17754
17804
|
authorized: info.authorized,
|
|
@@ -17862,7 +17912,8 @@ async function prepareWith(support, req, servername, cert) {
|
|
|
17862
17912
|
insecure: req.insecure === true,
|
|
17863
17913
|
...req.sni === false ? { sni: false } : {},
|
|
17864
17914
|
...req.checkHostname === false ? { checkHostname: false } : {},
|
|
17865
|
-
clientCertificate: cert !== void 0
|
|
17915
|
+
clientCertificate: cert !== void 0,
|
|
17916
|
+
bundled: own === void 0
|
|
17866
17917
|
};
|
|
17867
17918
|
let session;
|
|
17868
17919
|
try {
|
|
@@ -18449,9 +18500,21 @@ var VfsNode = class {
|
|
|
18449
18500
|
}
|
|
18450
18501
|
async keep() {
|
|
18451
18502
|
const ranged2 = await this.prepare();
|
|
18452
|
-
await ranged2
|
|
18503
|
+
if (ranged2) await this.followed(() => ranged2.pin());
|
|
18453
18504
|
}
|
|
18454
18505
|
moving = /* @__PURE__ */ new Set();
|
|
18506
|
+
async followed(op) {
|
|
18507
|
+
for (; ; ) {
|
|
18508
|
+
const at = this.path;
|
|
18509
|
+
try {
|
|
18510
|
+
return await op();
|
|
18511
|
+
} catch (err) {
|
|
18512
|
+
if (!isMissing(err)) throw err;
|
|
18513
|
+
while (this.moving.size > 0) await Promise.all(this.moving);
|
|
18514
|
+
if (this.path === at) throw err;
|
|
18515
|
+
}
|
|
18516
|
+
}
|
|
18517
|
+
}
|
|
18455
18518
|
async load() {
|
|
18456
18519
|
if (this.revoked) throw new KernelError("EIO");
|
|
18457
18520
|
while (!this.data) {
|
|
@@ -18497,7 +18560,7 @@ var VfsNode = class {
|
|
|
18497
18560
|
}
|
|
18498
18561
|
async pread(max, at) {
|
|
18499
18562
|
const ranged2 = await this.prepare();
|
|
18500
|
-
if (ranged2) return ranged2.read(at, max);
|
|
18563
|
+
if (ranged2) return this.followed(() => ranged2.read(at, max));
|
|
18501
18564
|
const bytes = await this.load();
|
|
18502
18565
|
const n = Math.max(0, Math.min(max, this.length - at));
|
|
18503
18566
|
return bytes.slice(at, at + n);
|
|
@@ -18540,7 +18603,7 @@ var VfsNode = class {
|
|
|
18540
18603
|
await this.fits(at + bytes.length);
|
|
18541
18604
|
const ranged2 = await this.prepare();
|
|
18542
18605
|
if (ranged2) {
|
|
18543
|
-
await ranged2.write(at, bytes);
|
|
18606
|
+
await this.followed(() => ranged2.write(at, bytes));
|
|
18544
18607
|
this.markDirty();
|
|
18545
18608
|
return bytes.length;
|
|
18546
18609
|
}
|
|
@@ -18609,8 +18672,9 @@ var VfsNode = class {
|
|
|
18609
18672
|
this.dirty = false;
|
|
18610
18673
|
const started = performance.now();
|
|
18611
18674
|
try {
|
|
18612
|
-
|
|
18613
|
-
|
|
18675
|
+
await this.followed(
|
|
18676
|
+
() => this.ranged ? this.ranged.flush() : this.fs.writeFile(this.path, this.data.slice(0, this.length))
|
|
18677
|
+
);
|
|
18614
18678
|
} catch (err) {
|
|
18615
18679
|
this.dirty = true;
|
|
18616
18680
|
throw err;
|
|
@@ -22589,6 +22653,79 @@ function scrubStdio(fds, scrubber) {
|
|
|
22589
22653
|
}
|
|
22590
22654
|
}
|
|
22591
22655
|
|
|
22656
|
+
// src/kernel/sealed-session.ts
|
|
22657
|
+
var SESSION_WINDOW_MS = 6e4;
|
|
22658
|
+
var SESSION_PLACEHOLDERS = 16;
|
|
22659
|
+
var SESSION_PLACEHOLDER = /^fnox_proxy_[0-9a-f]{24}$/;
|
|
22660
|
+
var SESSION_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
22661
|
+
var TOKEN5 = "[!#$%&'*+.^_`|~0-9a-z-]+";
|
|
22662
|
+
var HEADER = new RegExp(`^header:${TOKEN5}$`);
|
|
22663
|
+
var METHOD = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
22664
|
+
var TARGET = /^[\x21-\x7e]+$/;
|
|
22665
|
+
var EXIT = /^(page|proxy|tailscale|device:[\x21-\x7e]+)$/;
|
|
22666
|
+
var HOST = /^[a-z0-9.:-]+$/;
|
|
22667
|
+
var UNSAFE = /[\r\n\0]/;
|
|
22668
|
+
var POSITIONS = {
|
|
22669
|
+
http1: (position) => HEADER.test(position),
|
|
22670
|
+
smtp: (position) => position === "auth-plain" || position === "auth-login",
|
|
22671
|
+
pg: (position) => position === "password-cleartext"
|
|
22672
|
+
};
|
|
22673
|
+
function boundHost(servername) {
|
|
22674
|
+
const lower = servername.toLowerCase();
|
|
22675
|
+
return lower.endsWith(".") ? lower.slice(0, -1) : lower;
|
|
22676
|
+
}
|
|
22677
|
+
function headOk(f) {
|
|
22678
|
+
if (f.protocol !== "http1") return f.head === void 0;
|
|
22679
|
+
const head = f.head;
|
|
22680
|
+
return head !== void 0 && typeof head.method === "string" && METHOD.test(head.method) && typeof head.path === "string" && TARGET.test(head.path);
|
|
22681
|
+
}
|
|
22682
|
+
function placeholdersOk(list) {
|
|
22683
|
+
if (!Array.isArray(list) || list.length === 0 || list.length > SESSION_PLACEHOLDERS) return false;
|
|
22684
|
+
return new Set(list).size === list.length && list.every((p) => typeof p === "string" && SESSION_PLACEHOLDER.test(p));
|
|
22685
|
+
}
|
|
22686
|
+
function hostOk(host) {
|
|
22687
|
+
return typeof host === "string" && HOST.test(host) && boundHost(host) === host;
|
|
22688
|
+
}
|
|
22689
|
+
function sessionAskable(f, now) {
|
|
22690
|
+
if (!Object.hasOwn(POSITIONS, f.protocol) || typeof f.position !== "string") return false;
|
|
22691
|
+
if (!POSITIONS[f.protocol](f.position)) return false;
|
|
22692
|
+
if (typeof f.session !== "string" || !SESSION_ID.test(f.session)) return false;
|
|
22693
|
+
if (f.verified !== true || !hostOk(f.host) || typeof f.handshakeAt !== "number") return false;
|
|
22694
|
+
if (!Number.isInteger(f.port) || f.port < 1 || f.port > 65535) return false;
|
|
22695
|
+
const age = now - f.handshakeAt;
|
|
22696
|
+
if (!Number.isFinite(age) || age < 0 || age > SESSION_WINDOW_MS) return false;
|
|
22697
|
+
return typeof f.exit === "string" && EXIT.test(f.exit) && placeholdersOk(f.placeholders) && headOk(f);
|
|
22698
|
+
}
|
|
22699
|
+
function sessionRequest(f) {
|
|
22700
|
+
return {
|
|
22701
|
+
v: 1,
|
|
22702
|
+
op: "sessionMaterialize",
|
|
22703
|
+
caller: f.stamp,
|
|
22704
|
+
stamp: f.stamp,
|
|
22705
|
+
session: f.session,
|
|
22706
|
+
host: f.host,
|
|
22707
|
+
port: f.port,
|
|
22708
|
+
protocol: f.protocol,
|
|
22709
|
+
position: f.position,
|
|
22710
|
+
verified: true,
|
|
22711
|
+
handshakeAt: f.handshakeAt,
|
|
22712
|
+
exit: f.exit,
|
|
22713
|
+
placeholders: [...f.placeholders],
|
|
22714
|
+
...f.head ? { head: { method: f.head.method, path: f.head.path } } : {}
|
|
22715
|
+
};
|
|
22716
|
+
}
|
|
22717
|
+
function sessionValues(reply, asked) {
|
|
22718
|
+
if (typeof reply !== "object" || reply === null || Array.isArray(reply)) return void 0;
|
|
22719
|
+
const { error, values } = reply;
|
|
22720
|
+
if (error !== void 0 || typeof values !== "object" || values === null) return void 0;
|
|
22721
|
+
const out = {};
|
|
22722
|
+
for (const ph of asked) {
|
|
22723
|
+
const value2 = values[ph];
|
|
22724
|
+
if (typeof value2 === "string" && value2.length > 0 && !UNSAFE.test(value2)) out[ph] = value2;
|
|
22725
|
+
}
|
|
22726
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
22727
|
+
}
|
|
22728
|
+
|
|
22592
22729
|
// src/kernel/sealed.ts
|
|
22593
22730
|
var SEALED_MAX_BYTES = 64 * 1024;
|
|
22594
22731
|
var SEALED_TIMEOUT_MS = 1e4;
|
|
@@ -22783,6 +22920,15 @@ var SealedBroker = class {
|
|
|
22783
22920
|
};
|
|
22784
22921
|
}
|
|
22785
22922
|
async consume(fields) {
|
|
22923
|
+
const req = { ...fields, v: 1, op: "materializeConsume", caller: fields.stamp };
|
|
22924
|
+
return this.ask(req, swapOf);
|
|
22925
|
+
}
|
|
22926
|
+
async sessionMaterialize(fields, now = Date.now()) {
|
|
22927
|
+
if (!sessionAskable(fields, now)) return void 0;
|
|
22928
|
+
const req = sessionRequest(fields);
|
|
22929
|
+
return this.ask(req, (reply) => sessionValues(reply, req.placeholders));
|
|
22930
|
+
}
|
|
22931
|
+
async ask(req, parse) {
|
|
22786
22932
|
const { hook } = this;
|
|
22787
22933
|
if (!hook) return void 0;
|
|
22788
22934
|
const control = new AbortController();
|
|
@@ -22790,14 +22936,8 @@ var SealedBroker = class {
|
|
|
22790
22936
|
const stopped = new Promise((resolve2) => {
|
|
22791
22937
|
control.signal.addEventListener("abort", () => resolve2(void 0), { once: true });
|
|
22792
22938
|
});
|
|
22793
|
-
const req = {
|
|
22794
|
-
...fields,
|
|
22795
|
-
v: 1,
|
|
22796
|
-
op: "materializeConsume",
|
|
22797
|
-
caller: fields.stamp
|
|
22798
|
-
};
|
|
22799
22939
|
try {
|
|
22800
|
-
const asked = Promise.resolve().then(() => hook(req, { signal: control.signal })).then(
|
|
22940
|
+
const asked = Promise.resolve().then(() => hook(req, { signal: control.signal })).then(parse, () => void 0);
|
|
22801
22941
|
return await Promise.race([asked, stopped]);
|
|
22802
22942
|
} finally {
|
|
22803
22943
|
clearTimeout(timer);
|