@ai-ecoverse/slicc-kernel 1.74.0 → 1.75.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 +14 -0
- package/dist/index.js +56 -8
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +285 -27
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-process-worker.js +183 -34
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +263 -38
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +183 -34
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -736,9 +736,11 @@ var KernelPipe = class {
|
|
|
736
736
|
// src/kernel/fd-table.ts
|
|
737
737
|
var KernelError = class extends Error {
|
|
738
738
|
code;
|
|
739
|
-
|
|
739
|
+
detail;
|
|
740
|
+
constructor(code, detail) {
|
|
740
741
|
super(code);
|
|
741
742
|
this.code = code;
|
|
743
|
+
if (detail !== void 0) this.detail = detail;
|
|
742
744
|
}
|
|
743
745
|
};
|
|
744
746
|
function pollFile(file) {
|
|
@@ -881,6 +883,7 @@ function kernelFdKind(file) {
|
|
|
881
883
|
if (file.heldMeta && "device" in file.heldMeta) return "device";
|
|
882
884
|
if (file.tty) return "tty";
|
|
883
885
|
if (file.sealed) return "sealed";
|
|
886
|
+
if (file.clipboard) return "clipboard";
|
|
884
887
|
return file.seek ? "file" : "stream";
|
|
885
888
|
}
|
|
886
889
|
var FdTable = class _FdTable {
|
|
@@ -6070,6 +6073,173 @@ var ChildTable = class {
|
|
|
6070
6073
|
}
|
|
6071
6074
|
};
|
|
6072
6075
|
|
|
6076
|
+
// src/kernel/clipboard.ts
|
|
6077
|
+
var CLIPBOARD_MAX_BYTES = 1024 * 1024;
|
|
6078
|
+
var CLIPBOARD_TIMEOUT_MS = 1e4;
|
|
6079
|
+
var encoder = new TextEncoder();
|
|
6080
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
6081
|
+
var READY = { readable: true, writable: true, hangup: false };
|
|
6082
|
+
function lineOf(err) {
|
|
6083
|
+
const text = err instanceof Error ? err.message : String(err);
|
|
6084
|
+
return (text.split("\n")[0] ?? "").slice(0, 200);
|
|
6085
|
+
}
|
|
6086
|
+
function clipboardFailure(err) {
|
|
6087
|
+
if (err instanceof KernelError) return err;
|
|
6088
|
+
const name2 = err?.name;
|
|
6089
|
+
return new KernelError(name2 === "NotAllowedError" ? "EACCES" : "EIO", lineOf(err));
|
|
6090
|
+
}
|
|
6091
|
+
function joined2(chunks2, size) {
|
|
6092
|
+
if (chunks2.length === 1) return chunks2[0];
|
|
6093
|
+
const out = new Uint8Array(size);
|
|
6094
|
+
let at = 0;
|
|
6095
|
+
for (const chunk2 of chunks2) {
|
|
6096
|
+
out.set(chunk2, at);
|
|
6097
|
+
at += chunk2.length;
|
|
6098
|
+
}
|
|
6099
|
+
return out;
|
|
6100
|
+
}
|
|
6101
|
+
async function interruptible(work, signal) {
|
|
6102
|
+
if (!signal) return work;
|
|
6103
|
+
if (signal.aborted) throw new KernelError("EINTR");
|
|
6104
|
+
let stop = () => {
|
|
6105
|
+
};
|
|
6106
|
+
const interrupted2 = new Promise((_, reject) => {
|
|
6107
|
+
stop = () => reject(new KernelError("EINTR"));
|
|
6108
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
6109
|
+
});
|
|
6110
|
+
try {
|
|
6111
|
+
return await Promise.race([work, interrupted2]);
|
|
6112
|
+
} finally {
|
|
6113
|
+
signal.removeEventListener("abort", stop);
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
6116
|
+
var ClipboardChannel = class {
|
|
6117
|
+
stamp;
|
|
6118
|
+
access;
|
|
6119
|
+
broker;
|
|
6120
|
+
snapshot;
|
|
6121
|
+
taken;
|
|
6122
|
+
offset = 0;
|
|
6123
|
+
chunks = [];
|
|
6124
|
+
size = 0;
|
|
6125
|
+
wrote = false;
|
|
6126
|
+
failed = false;
|
|
6127
|
+
constructor(broker, access2, stamp) {
|
|
6128
|
+
this.broker = broker;
|
|
6129
|
+
this.access = access2;
|
|
6130
|
+
this.stamp = stamp;
|
|
6131
|
+
}
|
|
6132
|
+
get unread() {
|
|
6133
|
+
return this.taken === void 0 && this.snapshot === void 0;
|
|
6134
|
+
}
|
|
6135
|
+
get settled() {
|
|
6136
|
+
return this.taken !== void 0;
|
|
6137
|
+
}
|
|
6138
|
+
async read(max, signal) {
|
|
6139
|
+
if (this.access === "write") throw new KernelError("EBADF");
|
|
6140
|
+
if (!this.taken) {
|
|
6141
|
+
if (!this.snapshot) {
|
|
6142
|
+
const stamp = this.stamp;
|
|
6143
|
+
const asked = this.broker.ask(async (hook) => {
|
|
6144
|
+
const text = await hook.read(stamp);
|
|
6145
|
+
if (typeof text !== "string") throw new KernelError("EIO", "the clipboard gave no text");
|
|
6146
|
+
return encoder.encode(text);
|
|
6147
|
+
});
|
|
6148
|
+
this.snapshot = asked;
|
|
6149
|
+
asked.then(
|
|
6150
|
+
(bytes) => {
|
|
6151
|
+
if (this.snapshot === asked) this.taken = bytes;
|
|
6152
|
+
},
|
|
6153
|
+
() => {
|
|
6154
|
+
if (this.snapshot === asked) this.snapshot = void 0;
|
|
6155
|
+
}
|
|
6156
|
+
);
|
|
6157
|
+
}
|
|
6158
|
+
this.taken = await interruptible(this.snapshot, signal);
|
|
6159
|
+
}
|
|
6160
|
+
const out = this.taken.subarray(this.offset, this.offset + max);
|
|
6161
|
+
this.offset += out.length;
|
|
6162
|
+
return out;
|
|
6163
|
+
}
|
|
6164
|
+
write(bytes) {
|
|
6165
|
+
if (this.access === "read") throw new KernelError("EBADF");
|
|
6166
|
+
this.wrote = true;
|
|
6167
|
+
if (this.failed) throw new KernelError("EFBIG");
|
|
6168
|
+
if (this.size + bytes.length > CLIPBOARD_MAX_BYTES) {
|
|
6169
|
+
this.failed = true;
|
|
6170
|
+
this.chunks = [];
|
|
6171
|
+
this.size = 0;
|
|
6172
|
+
throw new KernelError("EFBIG");
|
|
6173
|
+
}
|
|
6174
|
+
if (bytes.length > 0) this.chunks.push(bytes.slice());
|
|
6175
|
+
this.size += bytes.length;
|
|
6176
|
+
return bytes.length;
|
|
6177
|
+
}
|
|
6178
|
+
poll() {
|
|
6179
|
+
return READY;
|
|
6180
|
+
}
|
|
6181
|
+
async close() {
|
|
6182
|
+
this.snapshot = void 0;
|
|
6183
|
+
this.taken = void 0;
|
|
6184
|
+
const commits = this.access === "write" || this.access === "both" && this.wrote;
|
|
6185
|
+
if (!commits || this.failed) return;
|
|
6186
|
+
const bytes = joined2(this.chunks, this.size);
|
|
6187
|
+
this.chunks = [];
|
|
6188
|
+
this.size = 0;
|
|
6189
|
+
let text;
|
|
6190
|
+
try {
|
|
6191
|
+
text = decoder.decode(bytes);
|
|
6192
|
+
} catch {
|
|
6193
|
+
throw new KernelError("EILSEQ", "the text is not valid UTF-8");
|
|
6194
|
+
}
|
|
6195
|
+
const stamp = this.stamp;
|
|
6196
|
+
await this.broker.ask(async (hook) => {
|
|
6197
|
+
await hook.write(text, stamp);
|
|
6198
|
+
});
|
|
6199
|
+
}
|
|
6200
|
+
};
|
|
6201
|
+
var ClipboardBroker = class {
|
|
6202
|
+
hook;
|
|
6203
|
+
users;
|
|
6204
|
+
timeoutMs;
|
|
6205
|
+
tagOf;
|
|
6206
|
+
constructor(hook, users, timeoutMs = CLIPBOARD_TIMEOUT_MS, tagOf = () => void 0) {
|
|
6207
|
+
this.hook = hook;
|
|
6208
|
+
this.users = users;
|
|
6209
|
+
this.timeoutMs = timeoutMs;
|
|
6210
|
+
this.tagOf = tagOf;
|
|
6211
|
+
}
|
|
6212
|
+
async ask(work) {
|
|
6213
|
+
const hook = this.hook;
|
|
6214
|
+
if (!hook) throw new KernelError("ENOTSUP", "no clipboard in this embedder");
|
|
6215
|
+
let timer;
|
|
6216
|
+
const late = new Promise((_, reject) => {
|
|
6217
|
+
timer = setTimeout(
|
|
6218
|
+
() => reject(new KernelError("EIO", "clipboard timed out")),
|
|
6219
|
+
this.timeoutMs
|
|
6220
|
+
);
|
|
6221
|
+
});
|
|
6222
|
+
const asked = Promise.resolve().then(() => work(hook)).catch((err) => {
|
|
6223
|
+
throw clipboardFailure(err);
|
|
6224
|
+
});
|
|
6225
|
+
try {
|
|
6226
|
+
return await Promise.race([asked, late]);
|
|
6227
|
+
} finally {
|
|
6228
|
+
clearTimeout(timer);
|
|
6229
|
+
}
|
|
6230
|
+
}
|
|
6231
|
+
open(access2, stamp) {
|
|
6232
|
+
const channel = new ClipboardChannel(this, access2, stamp);
|
|
6233
|
+
return new OpenFile({
|
|
6234
|
+
read: (max, signal) => channel.read(max, signal),
|
|
6235
|
+
write: async (bytes) => channel.write(bytes),
|
|
6236
|
+
poll: () => channel.poll(),
|
|
6237
|
+
close: () => channel.close(),
|
|
6238
|
+
clipboard: channel
|
|
6239
|
+
});
|
|
6240
|
+
}
|
|
6241
|
+
};
|
|
6242
|
+
|
|
6073
6243
|
// src/mount/protocol.ts
|
|
6074
6244
|
var DRIVER_PROTOCOL = [1, 2];
|
|
6075
6245
|
function driverVersionError(theirs) {
|
|
@@ -7607,20 +7777,20 @@ var SAB_DEFAULT_WINDOW_BYTES = 1024 * 1024;
|
|
|
7607
7777
|
var SAB_MIN_BYTES = SAB_HEADER_BYTES + 4096;
|
|
7608
7778
|
var SYNC_SAB_REQ_MSG = "sync-sab-req";
|
|
7609
7779
|
var SYNC_SAB_NEXT_MSG = "sync-sab-next";
|
|
7610
|
-
var
|
|
7611
|
-
var
|
|
7780
|
+
var encoder2 = new TextEncoder();
|
|
7781
|
+
var decoder2 = new TextDecoder();
|
|
7612
7782
|
function encodeSabResult(result) {
|
|
7613
7783
|
if (!result.ok) {
|
|
7614
7784
|
return {
|
|
7615
7785
|
status: SAB_STATUS_ERRNO,
|
|
7616
|
-
payload:
|
|
7786
|
+
payload: encoder2.encode(JSON.stringify({ errno: result.errno, message: result.message }))
|
|
7617
7787
|
};
|
|
7618
7788
|
}
|
|
7619
7789
|
switch (result.kind) {
|
|
7620
7790
|
case "bytes":
|
|
7621
7791
|
return { status: SAB_STATUS_BYTES, payload: result.bytes };
|
|
7622
7792
|
case "json":
|
|
7623
|
-
return { status: SAB_STATUS_JSON, payload:
|
|
7793
|
+
return { status: SAB_STATUS_JSON, payload: encoder2.encode(JSON.stringify(result.json)) };
|
|
7624
7794
|
default:
|
|
7625
7795
|
return { status: SAB_STATUS_VOID, payload: new Uint8Array(0) };
|
|
7626
7796
|
}
|
|
@@ -10442,7 +10612,7 @@ function defaultTermios() {
|
|
|
10442
10612
|
c_cc: cCc
|
|
10443
10613
|
};
|
|
10444
10614
|
}
|
|
10445
|
-
var
|
|
10615
|
+
var encoder3 = new TextEncoder();
|
|
10446
10616
|
function isContinuation(byte) {
|
|
10447
10617
|
return (byte & 192) === 128;
|
|
10448
10618
|
}
|
|
@@ -10564,7 +10734,7 @@ var KernelTty = class {
|
|
|
10564
10734
|
this.line.push(byte);
|
|
10565
10735
|
this.readable.push(Uint8Array.from(this.line));
|
|
10566
10736
|
this.line = [];
|
|
10567
|
-
if (echo) this.output(
|
|
10737
|
+
if (echo) this.output(encoder3.encode("\n"));
|
|
10568
10738
|
} else {
|
|
10569
10739
|
this.line.push(byte);
|
|
10570
10740
|
if (echo) this.echo(byte);
|
|
@@ -10589,7 +10759,7 @@ var KernelTty = class {
|
|
|
10589
10759
|
const utf82 = (this.termios.c_iflag & IUTF8) !== 0;
|
|
10590
10760
|
const cells = utf82 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
|
|
10591
10761
|
if (cells > 0 && this.termios.c_lflag & ECHO) {
|
|
10592
|
-
this.output(
|
|
10762
|
+
this.output(encoder3.encode("\b \b".repeat(cells)), false);
|
|
10593
10763
|
}
|
|
10594
10764
|
}
|
|
10595
10765
|
echo(byte) {
|
|
@@ -11078,7 +11248,7 @@ async function socketSyscall(req, proc) {
|
|
|
11078
11248
|
dialing?.catch(() => void 0);
|
|
11079
11249
|
throw new KernelError("EINPROGRESS");
|
|
11080
11250
|
}
|
|
11081
|
-
if (dialing !== void 0) await
|
|
11251
|
+
if (dialing !== void 0) await interruptible2(dialing, proc.blocking());
|
|
11082
11252
|
return ok();
|
|
11083
11253
|
}
|
|
11084
11254
|
case "sock-shutdown":
|
|
@@ -11102,7 +11272,7 @@ async function socketSyscall(req, proc) {
|
|
|
11102
11272
|
}
|
|
11103
11273
|
}
|
|
11104
11274
|
}
|
|
11105
|
-
function
|
|
11275
|
+
function interruptible2(dialing, signal) {
|
|
11106
11276
|
return new Promise((resolve, reject) => {
|
|
11107
11277
|
const abort = () => reject(new KernelError("EINTR"));
|
|
11108
11278
|
signal.addEventListener("abort", abort, { once: true });
|
|
@@ -11769,6 +11939,7 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
|
|
|
11769
11939
|
"fd-tty-names",
|
|
11770
11940
|
"fd-tty-owner",
|
|
11771
11941
|
"fd-open-sealed",
|
|
11942
|
+
"fd-open-clipboard",
|
|
11772
11943
|
"tty-get",
|
|
11773
11944
|
"tty-set",
|
|
11774
11945
|
"tty-winsz",
|
|
@@ -12011,7 +12182,7 @@ var WasmProcess = class {
|
|
|
12011
12182
|
return await this.procSyscall(req, cancelled);
|
|
12012
12183
|
} catch (e) {
|
|
12013
12184
|
if (e instanceof KernelError || e instanceof SpawnError) {
|
|
12014
|
-
return { ok: false, errno: e.code, message: e.code };
|
|
12185
|
+
return { ok: false, errno: e.code, message: e.detail ?? e.code };
|
|
12015
12186
|
}
|
|
12016
12187
|
const code = e?.code;
|
|
12017
12188
|
if (typeof code === "string" && /^E[A-Z]+$/.test(code)) {
|
|
@@ -12054,6 +12225,7 @@ var WasmProcess = class {
|
|
|
12054
12225
|
const read = req.peek ? file.peek : file.read;
|
|
12055
12226
|
if (!read) throw new KernelError(req.peek && file.read ? "EOPNOTSUPP" : "EBADF");
|
|
12056
12227
|
if (file.tty) this.checkForeground(file.tty);
|
|
12228
|
+
if (file.clipboard) return this.readClipboard(file.clipboard, req, cancelled);
|
|
12057
12229
|
if (req.max <= 0) return new Uint8Array(0);
|
|
12058
12230
|
if (file instanceof KernelSocket && file.unconnected) throw new KernelError("ENOTCONN");
|
|
12059
12231
|
const ready2 = pollFile(file).readable;
|
|
@@ -12061,6 +12233,13 @@ var WasmProcess = class {
|
|
|
12061
12233
|
const signal = ready2 ? this.interrupt.signal : this.blockingSignal(cancelled);
|
|
12062
12234
|
return read.call(file, Math.max(0, Math.min(req.max, MAX_READ)), signal);
|
|
12063
12235
|
}
|
|
12236
|
+
async readClipboard(channel, req, cancelled) {
|
|
12237
|
+
if (channel.access === "write") throw new KernelError("EBADF");
|
|
12238
|
+
if (req.max <= 0) return new Uint8Array(0);
|
|
12239
|
+
if (channel.unread) channel.stamp = await this.clipboardStamp();
|
|
12240
|
+
const signal = channel.settled ? this.interrupt.signal : this.blockingSignal(cancelled);
|
|
12241
|
+
return channel.read(Math.min(req.max, MAX_READ), signal);
|
|
12242
|
+
}
|
|
12064
12243
|
async write(fd, body, nonblock = false, cancelled) {
|
|
12065
12244
|
const file = this.fds.get(fd).file;
|
|
12066
12245
|
if (file.sealed) return file.sealed.send(body, await this.sealedCaller(), this.gone.signal);
|
|
@@ -12164,6 +12343,36 @@ var WasmProcess = class {
|
|
|
12164
12343
|
if (!broker) throw new KernelError("ENOENT");
|
|
12165
12344
|
return this.fds.install(broker.open(), 3);
|
|
12166
12345
|
}
|
|
12346
|
+
async openClipboard(flags2) {
|
|
12347
|
+
const broker = this.options.clipboard;
|
|
12348
|
+
if (!broker) throw new KernelError("ENOENT");
|
|
12349
|
+
const mode = flags2 & WRITE_ACCESS;
|
|
12350
|
+
const access2 = mode === 0 ? "read" : mode === 1 ? "write" : "both";
|
|
12351
|
+
return this.fds.install(broker.open(access2, await this.clipboardStamp()), 3);
|
|
12352
|
+
}
|
|
12353
|
+
async clipboardStamp() {
|
|
12354
|
+
const shown = await this.options.identity?.();
|
|
12355
|
+
const broker = this.options.clipboard;
|
|
12356
|
+
const tag = broker.tagOf(this.pid);
|
|
12357
|
+
return {
|
|
12358
|
+
pid: shown?.pid ?? this.pid,
|
|
12359
|
+
uid: this.cred.euid,
|
|
12360
|
+
gid: this.cred.egid,
|
|
12361
|
+
users: broker.users,
|
|
12362
|
+
...tag !== void 0 ? { tag } : {}
|
|
12363
|
+
};
|
|
12364
|
+
}
|
|
12365
|
+
async stampClipboards() {
|
|
12366
|
+
if (!this.options.clipboard) return;
|
|
12367
|
+
const open = this.fds.numbers().filter((fd) => this.fds.get(fd).file.clipboard);
|
|
12368
|
+
if (open.length === 0) return;
|
|
12369
|
+
const stamp = await this.clipboardStamp().catch(() => void 0);
|
|
12370
|
+
if (!stamp) return;
|
|
12371
|
+
for (const fd of open) {
|
|
12372
|
+
const channel = this.fds.get(fd).file.clipboard;
|
|
12373
|
+
if (channel) channel.stamp = stamp;
|
|
12374
|
+
}
|
|
12375
|
+
}
|
|
12167
12376
|
async sealedCaller() {
|
|
12168
12377
|
const shown = await this.options.identity?.();
|
|
12169
12378
|
const broker = this.options.sealed;
|
|
@@ -12238,10 +12447,13 @@ var WasmProcess = class {
|
|
|
12238
12447
|
kind: "json",
|
|
12239
12448
|
json: await this.write(req.fd, req.body, req.nonblock, cancelled)
|
|
12240
12449
|
};
|
|
12241
|
-
case "fd-close":
|
|
12450
|
+
case "fd-close": {
|
|
12242
12451
|
this.options.locks?.closed(this.pid, req.fd);
|
|
12452
|
+
const channel = this.fds.get(req.fd).file.clipboard;
|
|
12453
|
+
if (channel) channel.stamp = await this.clipboardStamp();
|
|
12243
12454
|
await Promise.resolve(this.fds.close(req.fd));
|
|
12244
12455
|
return { ok: true, kind: "void" };
|
|
12456
|
+
}
|
|
12245
12457
|
case "fd-pipe": {
|
|
12246
12458
|
const pipe = openPipe();
|
|
12247
12459
|
const read = this.fds.install(pipe.read, 3);
|
|
@@ -12299,6 +12511,8 @@ var WasmProcess = class {
|
|
|
12299
12511
|
return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
|
|
12300
12512
|
case "fd-open-sealed":
|
|
12301
12513
|
return { ok: true, kind: "json", json: this.openSealed() };
|
|
12514
|
+
case "fd-open-clipboard":
|
|
12515
|
+
return { ok: true, kind: "json", json: await this.openClipboard(req.flags) };
|
|
12302
12516
|
case "fd-tty-owner":
|
|
12303
12517
|
return { ok: true, kind: "json", json: this.terminalByName(req.name).owner ?? null };
|
|
12304
12518
|
case "fd-select": {
|
|
@@ -12750,6 +12964,7 @@ var WasmProcess = class {
|
|
|
12750
12964
|
this.options.locks?.release(this.pid);
|
|
12751
12965
|
this.asyncOps.close();
|
|
12752
12966
|
for (const pid of this.children.pids()) this.options.onReap?.(pid);
|
|
12967
|
+
await this.stampClipboards();
|
|
12753
12968
|
await this.fds.closeAll();
|
|
12754
12969
|
if (!this.options.nodes) this.options.openFiles?.delete(this.nodes);
|
|
12755
12970
|
await this.options.http?.closeAll();
|
|
@@ -12932,6 +13147,7 @@ function processOptions(opts, header4, hooks, created3) {
|
|
|
12932
13147
|
...inherited(opts),
|
|
12933
13148
|
...opts.owners ? { owners: true } : {},
|
|
12934
13149
|
...opts.sealed ? { sealed: opts.sealed } : {},
|
|
13150
|
+
...opts.clipboard ? { clipboard: opts.clipboard } : {},
|
|
12935
13151
|
...opts.readonlyAt ? { readonlyAt: opts.readonlyAt } : {},
|
|
12936
13152
|
...opts.dac ? { guard: { dac: opts.dac, fs: opts.fs, created: created3 } } : {},
|
|
12937
13153
|
...opts.identity ? { identity: opts.identity } : {},
|
|
@@ -13436,14 +13652,14 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
|
|
|
13436
13652
|
"cancel",
|
|
13437
13653
|
"materialize"
|
|
13438
13654
|
]);
|
|
13439
|
-
var
|
|
13440
|
-
var
|
|
13655
|
+
var encoder4 = new TextEncoder();
|
|
13656
|
+
var decoder3 = new TextDecoder("utf-8", { fatal: true });
|
|
13441
13657
|
function parseSealed(bytes) {
|
|
13442
13658
|
try {
|
|
13443
13659
|
if (bytes.length > SEALED_MAX_BYTES) throw new KernelError("EMSGSIZE");
|
|
13444
13660
|
let parsed2;
|
|
13445
13661
|
try {
|
|
13446
|
-
parsed2 = JSON.parse(
|
|
13662
|
+
parsed2 = JSON.parse(decoder3.decode(bytes));
|
|
13447
13663
|
} catch {
|
|
13448
13664
|
throw new KernelError("EINVAL");
|
|
13449
13665
|
}
|
|
@@ -13469,13 +13685,13 @@ function serialized(reply) {
|
|
|
13469
13685
|
const text = JSON.stringify(reply);
|
|
13470
13686
|
plain = text === void 0 ? void 0 : JSON.parse(text);
|
|
13471
13687
|
} catch (err) {
|
|
13472
|
-
return JSON.stringify(errorReply("EIO",
|
|
13688
|
+
return JSON.stringify(errorReply("EIO", lineOf2(err)));
|
|
13473
13689
|
}
|
|
13474
13690
|
if (!isRecord(plain)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
|
|
13475
13691
|
const { v: _, ...rest2 } = plain;
|
|
13476
13692
|
return JSON.stringify({ v: 1, ...rest2 });
|
|
13477
13693
|
}
|
|
13478
|
-
function
|
|
13694
|
+
function lineOf2(err) {
|
|
13479
13695
|
const text = err instanceof Error ? err.message : String(err);
|
|
13480
13696
|
return (text.split("\n")[0] ?? "").slice(0, 200);
|
|
13481
13697
|
}
|
|
@@ -13505,7 +13721,7 @@ var SealedChannel = class {
|
|
|
13505
13721
|
gone.removeEventListener("abort", withdraw);
|
|
13506
13722
|
if (this.inflight !== flight) return;
|
|
13507
13723
|
this.inflight = void 0;
|
|
13508
|
-
if (reply) this.reply =
|
|
13724
|
+
if (reply) this.reply = encoder4.encode(serialized(reply));
|
|
13509
13725
|
});
|
|
13510
13726
|
this.inflight = flight;
|
|
13511
13727
|
return length2;
|
|
@@ -13519,7 +13735,7 @@ var SealedChannel = class {
|
|
|
13519
13735
|
if (signal.aborted) return void 0;
|
|
13520
13736
|
const asked = Promise.resolve().then(() => hook(req, { signal })).then(
|
|
13521
13737
|
(reply2) => isRecord(reply2) ? reply2 : errorReply("EIO", "the vault gave no reply"),
|
|
13522
|
-
(err) => errorReply("EIO",
|
|
13738
|
+
(err) => errorReply("EIO", lineOf2(err))
|
|
13523
13739
|
);
|
|
13524
13740
|
const reply = await Promise.race([asked, stopped]);
|
|
13525
13741
|
if (!signal.aborted) return reply;
|
|
@@ -14242,13 +14458,13 @@ var HostfsClient = class {
|
|
|
14242
14458
|
const response = await this.send("/api/hostfs/watch", { method: "POST", signal });
|
|
14243
14459
|
onOpen();
|
|
14244
14460
|
const reader = response.body.getReader();
|
|
14245
|
-
const
|
|
14461
|
+
const decoder4 = new TextDecoder();
|
|
14246
14462
|
let buffered = "";
|
|
14247
14463
|
try {
|
|
14248
14464
|
for (; ; ) {
|
|
14249
14465
|
const { done: done4, value } = await reader.read();
|
|
14250
14466
|
if (done4) return;
|
|
14251
|
-
buffered +=
|
|
14467
|
+
buffered += decoder4.decode(value, { stream: true });
|
|
14252
14468
|
let end = buffered.indexOf("\n");
|
|
14253
14469
|
while (end >= 0) {
|
|
14254
14470
|
const line = buffered.slice(0, end).trim();
|
|
@@ -15730,7 +15946,7 @@ var LAYOUT = [
|
|
|
15730
15946
|
];
|
|
15731
15947
|
var LOAD_SAMPLE_MS = 5e3;
|
|
15732
15948
|
var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
|
|
15733
|
-
var
|
|
15949
|
+
var encoder5 = new TextEncoder();
|
|
15734
15950
|
var USERS_MODES = ["off", "report", "enforce"];
|
|
15735
15951
|
function usersMode(mode = "off") {
|
|
15736
15952
|
if (USERS_MODES.includes(mode)) return mode;
|
|
@@ -15887,6 +16103,7 @@ var Launcher = class {
|
|
|
15887
16103
|
usersMode;
|
|
15888
16104
|
dac;
|
|
15889
16105
|
sealed;
|
|
16106
|
+
clipboard;
|
|
15890
16107
|
rootFs;
|
|
15891
16108
|
fileWatches;
|
|
15892
16109
|
nextPid = 1e3;
|
|
@@ -15897,6 +16114,12 @@ var Launcher = class {
|
|
|
15897
16114
|
this.rootFs = options.fs;
|
|
15898
16115
|
this.dac = this.usersMode === "off" ? void 0 : new Dac(this.usersMode, options.onDenial);
|
|
15899
16116
|
if (this.dac) this.dac.tagOf = (pid) => this.tagOf(pid);
|
|
16117
|
+
this.clipboard = new ClipboardBroker(
|
|
16118
|
+
options.clipboard,
|
|
16119
|
+
this.usersMode,
|
|
16120
|
+
void 0,
|
|
16121
|
+
(pid) => this.tagOf(pid)
|
|
16122
|
+
);
|
|
15900
16123
|
this.sealed = new SealedBroker(
|
|
15901
16124
|
options.sealed,
|
|
15902
16125
|
this.usersMode,
|
|
@@ -16313,6 +16536,7 @@ var Launcher = class {
|
|
|
16313
16536
|
cred: req.cred,
|
|
16314
16537
|
...this.owners ? { owners: true } : {},
|
|
16315
16538
|
sealed: this.sealed,
|
|
16539
|
+
clipboard: this.clipboard,
|
|
16316
16540
|
...this.dac ? { dac: this.dac } : {},
|
|
16317
16541
|
program: req.program,
|
|
16318
16542
|
argv0: req.argv0,
|
|
@@ -17073,7 +17297,7 @@ var Launcher = class {
|
|
|
17073
17297
|
},
|
|
17074
17298
|
account
|
|
17075
17299
|
);
|
|
17076
|
-
const report = (message3) => options.onData(
|
|
17300
|
+
const report = (message3) => options.onData(encoder5.encode(`${message3}\r
|
|
17077
17301
|
`));
|
|
17078
17302
|
const handle = await this.launch(planned, {
|
|
17079
17303
|
env,
|
|
@@ -17110,7 +17334,7 @@ var Launcher = class {
|
|
|
17110
17334
|
};
|
|
17111
17335
|
const stdout = collect(out, options.onStdout);
|
|
17112
17336
|
const stderr = collect(err, options.onStderr);
|
|
17113
|
-
const report = (message3) => stderr(
|
|
17337
|
+
const report = (message3) => stderr(encoder5.encode(`${message3}
|
|
17114
17338
|
`));
|
|
17115
17339
|
if (!planned) {
|
|
17116
17340
|
report(`${file}: command not found`);
|
|
@@ -17647,7 +17871,7 @@ function dialStream(port, onClose) {
|
|
|
17647
17871
|
|
|
17648
17872
|
// src/client/loopback-fetch.ts
|
|
17649
17873
|
var OWN_HEADERS = /* @__PURE__ */ new Set(["host", "connection", "content-length", "transfer-encoding"]);
|
|
17650
|
-
var
|
|
17874
|
+
var encoder6 = new TextEncoder();
|
|
17651
17875
|
var latin12 = new TextDecoder("latin1");
|
|
17652
17876
|
var ByteSource = class {
|
|
17653
17877
|
buffered = new Uint8Array(0);
|
|
@@ -17658,14 +17882,14 @@ var ByteSource = class {
|
|
|
17658
17882
|
async more() {
|
|
17659
17883
|
const { done: done4, value } = await this.reader.read();
|
|
17660
17884
|
if (done4) return false;
|
|
17661
|
-
const
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
this.buffered =
|
|
17885
|
+
const joined3 = new Uint8Array(this.buffered.length + value.length);
|
|
17886
|
+
joined3.set(this.buffered);
|
|
17887
|
+
joined3.set(value, this.buffered.length);
|
|
17888
|
+
this.buffered = joined3;
|
|
17665
17889
|
return true;
|
|
17666
17890
|
}
|
|
17667
17891
|
async until(marker) {
|
|
17668
|
-
const needle =
|
|
17892
|
+
const needle = encoder6.encode(marker);
|
|
17669
17893
|
for (; ; ) {
|
|
17670
17894
|
const at = indexOf(this.buffered, needle);
|
|
17671
17895
|
if (at >= 0) return this.take(at + needle.length);
|
|
@@ -17773,7 +17997,7 @@ async function requestBytes(request) {
|
|
|
17773
17997
|
});
|
|
17774
17998
|
if (body) lines2.push(`Content-Length: ${body.length}`);
|
|
17775
17999
|
lines2.push("Connection: close", "", "");
|
|
17776
|
-
const head =
|
|
18000
|
+
const head = encoder6.encode(lines2.join("\r\n"));
|
|
17777
18001
|
const out = new Uint8Array(head.length + (body?.length ?? 0));
|
|
17778
18002
|
out.set(head);
|
|
17779
18003
|
if (body) out.set(body, head.length);
|
|
@@ -17827,8 +18051,8 @@ var KernelCallError = class extends Error {
|
|
|
17827
18051
|
this.code = code;
|
|
17828
18052
|
}
|
|
17829
18053
|
};
|
|
17830
|
-
var
|
|
17831
|
-
var bytesOf2 = (data) => typeof data === "string" ?
|
|
18054
|
+
var encoder7 = new TextEncoder();
|
|
18055
|
+
var bytesOf2 = (data) => typeof data === "string" ? encoder7.encode(data) : data;
|
|
17832
18056
|
var UNAVAILABLE = {
|
|
17833
18057
|
manualRedirects: false,
|
|
17834
18058
|
encodedBodies: false,
|
|
@@ -18246,8 +18470,8 @@ function nodeWorker(file, live, closed) {
|
|
|
18246
18470
|
}
|
|
18247
18471
|
function textOf(on) {
|
|
18248
18472
|
if (!on) return void 0;
|
|
18249
|
-
const
|
|
18250
|
-
return (bytes) => on(
|
|
18473
|
+
const decoder4 = new TextDecoder();
|
|
18474
|
+
return (bytes) => on(decoder4.decode(bytes, { stream: true }));
|
|
18251
18475
|
}
|
|
18252
18476
|
async function createNodeKernel(options = {}) {
|
|
18253
18477
|
const root = options.root ?? memoryRoot();
|
|
@@ -18282,6 +18506,7 @@ async function createNodeKernel(options = {}) {
|
|
|
18282
18506
|
...options.onDenial ? { onDenial: options.onDenial } : {},
|
|
18283
18507
|
...options.protect ? { protect: options.protect } : {},
|
|
18284
18508
|
...options.sealed ? { sealed: options.sealed } : {},
|
|
18509
|
+
...options.clipboard ? { clipboard: options.clipboard } : {},
|
|
18285
18510
|
...options.approve ? { approve: options.approve } : {}
|
|
18286
18511
|
});
|
|
18287
18512
|
await launcher.prepare();
|
|
@@ -18290,7 +18515,7 @@ async function createNodeKernel(options = {}) {
|
|
|
18290
18515
|
pending.add(reject);
|
|
18291
18516
|
work().then(resolve, reject).finally(() => pending.delete(reject));
|
|
18292
18517
|
});
|
|
18293
|
-
const
|
|
18518
|
+
const decoder4 = new TextDecoder();
|
|
18294
18519
|
return {
|
|
18295
18520
|
root,
|
|
18296
18521
|
async run(argv, opts = {}) {
|
|
@@ -18307,8 +18532,8 @@ async function createNodeKernel(options = {}) {
|
|
|
18307
18532
|
);
|
|
18308
18533
|
return {
|
|
18309
18534
|
status: result.status,
|
|
18310
|
-
stdout:
|
|
18311
|
-
stderr:
|
|
18535
|
+
stdout: decoder4.decode(result.stdout),
|
|
18536
|
+
stderr: decoder4.decode(result.stderr)
|
|
18312
18537
|
};
|
|
18313
18538
|
},
|
|
18314
18539
|
async openTerminal(argv, opts = {}) {
|