sandboxedjs 0.1.67 → 0.1.69
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/dist/index.cjs +189 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +189 -6
- package/dist/index.js.map +1 -1
- package/dist/python/python.data +270 -273
- package/dist/python/python.js +1 -1
- package/dist/python/python.wasm +0 -0
- package/dist/python/runtime.json +3 -3
- package/dist/python-abi.cjs +45 -1
- package/dist/python-abi.cjs.map +1 -1
- package/dist/python-abi.d.cts +34 -0
- package/dist/python-abi.d.ts +34 -0
- package/dist/python-abi.js +45 -1
- package/dist/python-abi.js.map +1 -1
- package/dist/python-worker.js +13 -1
- package/dist/python-worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -489,6 +489,9 @@ function normalizeSignal(spec) {
|
|
|
489
489
|
const withPrefix = upper.startsWith("SIG") ? upper : "SIG" + upper;
|
|
490
490
|
return withPrefix in SIGNALS ? withPrefix : null;
|
|
491
491
|
}
|
|
492
|
+
function signalNumber(name) {
|
|
493
|
+
return SIGNALS[name] ?? 0;
|
|
494
|
+
}
|
|
492
495
|
function exitCodeForSignal(sig) {
|
|
493
496
|
return 128 + (SIGNALS[sig] ?? 0);
|
|
494
497
|
}
|
|
@@ -17800,7 +17803,10 @@ var Op = {
|
|
|
17800
17803
|
getpeername: 1801,
|
|
17801
17804
|
setsockopt: 1802,
|
|
17802
17805
|
getsockopt: 1803,
|
|
17803
|
-
socket_close: 1804
|
|
17806
|
+
socket_close: 1804,
|
|
17807
|
+
spawn: 2048,
|
|
17808
|
+
waitpid: 2049,
|
|
17809
|
+
kill: 2050
|
|
17804
17810
|
};
|
|
17805
17811
|
var Errno = {
|
|
17806
17812
|
EPERM: 1,
|
|
@@ -17811,6 +17817,7 @@ var Errno = {
|
|
|
17811
17817
|
ENXIO: 6,
|
|
17812
17818
|
E2BIG: 7,
|
|
17813
17819
|
EBADF: 9,
|
|
17820
|
+
ECHILD: 10,
|
|
17814
17821
|
EAGAIN: 11,
|
|
17815
17822
|
ENOMEM: 12,
|
|
17816
17823
|
EACCES: 13,
|
|
@@ -17946,7 +17953,7 @@ var wheels_default = {
|
|
|
17946
17953
|
|
|
17947
17954
|
// package.json
|
|
17948
17955
|
var package_default = {
|
|
17949
|
-
version: "0.1.
|
|
17956
|
+
version: "0.1.69"};
|
|
17950
17957
|
|
|
17951
17958
|
// src/runtime/python/config.ts
|
|
17952
17959
|
var bundledManifest = {
|
|
@@ -18491,6 +18498,9 @@ function toPosixError(error) {
|
|
|
18491
18498
|
};
|
|
18492
18499
|
return new PosixError(code && mapped[code] ? mapped[code] : Errno.EIO, message);
|
|
18493
18500
|
}
|
|
18501
|
+
|
|
18502
|
+
// src/runtime/python/backend.ts
|
|
18503
|
+
init_signals();
|
|
18494
18504
|
var DescriptorTable = class _DescriptorTable {
|
|
18495
18505
|
slots = /* @__PURE__ */ new Map();
|
|
18496
18506
|
/** Descriptions this table shares with others, so close counts correctly. */
|
|
@@ -19384,6 +19394,46 @@ function createHostAbiServer(proc) {
|
|
|
19384
19394
|
const joined = Object.entries(proc.env).map(([key, value]) => `${key}=${value}`).join("\0");
|
|
19385
19395
|
return { status: 0, payload: new Writer().string(joined).finish() };
|
|
19386
19396
|
}
|
|
19397
|
+
/* --------------------------------------------------------- processes */
|
|
19398
|
+
case Op.spawn: {
|
|
19399
|
+
const argv = [];
|
|
19400
|
+
for (let i = 0, n = r.u32(); i < n; i++) argv.push(r.string());
|
|
19401
|
+
const env2 = {};
|
|
19402
|
+
for (let i = 0, n = r.u32(); i < n; i++) {
|
|
19403
|
+
const entry = r.string();
|
|
19404
|
+
const split2 = entry.indexOf("=");
|
|
19405
|
+
if (split2 > 0) env2[entry.slice(0, split2)] = entry.slice(split2 + 1);
|
|
19406
|
+
}
|
|
19407
|
+
const cwd = r.string() || proc.cwd;
|
|
19408
|
+
const files2 = /* @__PURE__ */ new Map();
|
|
19409
|
+
for (let i = 0, n = r.u32(); i < n; i++) {
|
|
19410
|
+
const childFd = r.u32() | 0;
|
|
19411
|
+
const parentFd = r.u32() | 0;
|
|
19412
|
+
files2.set(childFd, proc.table.get(parentFd));
|
|
19413
|
+
}
|
|
19414
|
+
if (!proc.processes) throw new PosixError(Errno.ENOSYS);
|
|
19415
|
+
if (argv.length === 0) throw new PosixError(Errno.EINVAL);
|
|
19416
|
+
return { status: await proc.processes.spawn({ argv, env: env2, cwd: resolve3(cwd), files: files2 }) };
|
|
19417
|
+
}
|
|
19418
|
+
case Op.waitpid: {
|
|
19419
|
+
const pid = r.u32() | 0;
|
|
19420
|
+
const options = r.u32() | 0;
|
|
19421
|
+
if (!proc.processes) throw new PosixError(Errno.ENOSYS);
|
|
19422
|
+
const result = await Promise.race([
|
|
19423
|
+
proc.processes.wait(pid, options),
|
|
19424
|
+
aborted().then(() => {
|
|
19425
|
+
throw new PosixError(Errno.EINTR);
|
|
19426
|
+
})
|
|
19427
|
+
]);
|
|
19428
|
+
return { status: 0, payload: new Writer().i32(result.pid).i32(result.status).finish() };
|
|
19429
|
+
}
|
|
19430
|
+
case Op.kill: {
|
|
19431
|
+
const pid = r.u32() | 0;
|
|
19432
|
+
const signal = r.u32() | 0;
|
|
19433
|
+
if (!proc.processes) throw new PosixError(Errno.ENOSYS);
|
|
19434
|
+
proc.processes.kill(pid, signal);
|
|
19435
|
+
return { status: 0 };
|
|
19436
|
+
}
|
|
19387
19437
|
/* ---------------------------------------------------------- entropy */
|
|
19388
19438
|
case Op.getrandom: {
|
|
19389
19439
|
const length = Math.min(r.u32(), 65536);
|
|
@@ -19737,6 +19787,7 @@ async function startPythonProcess(options) {
|
|
|
19737
19787
|
table.set(0, stdin);
|
|
19738
19788
|
table.set(1, stdout);
|
|
19739
19789
|
table.set(2, stderr);
|
|
19790
|
+
for (const [fd, description] of options.inherit ?? []) table.set(fd, description);
|
|
19740
19791
|
const controller = new AbortController();
|
|
19741
19792
|
const abort = () => controller.abort();
|
|
19742
19793
|
options.signal.addEventListener("abort", abort, { once: true });
|
|
@@ -19750,7 +19801,8 @@ async function startPythonProcess(options) {
|
|
|
19750
19801
|
env: options.env,
|
|
19751
19802
|
cwd: options.cwd,
|
|
19752
19803
|
signal: controller.signal,
|
|
19753
|
-
sockets: options.sockets
|
|
19804
|
+
sockets: options.sockets,
|
|
19805
|
+
processes: options.processes
|
|
19754
19806
|
});
|
|
19755
19807
|
const buffers = createHostTransportBuffers();
|
|
19756
19808
|
let fault = null;
|
|
@@ -19815,7 +19867,11 @@ async function startPythonProcess(options) {
|
|
|
19815
19867
|
pid: options.pid,
|
|
19816
19868
|
ppid: options.ppid,
|
|
19817
19869
|
mounts: options.mounts,
|
|
19818
|
-
isTty: options.isTty
|
|
19870
|
+
isTty: options.isTty,
|
|
19871
|
+
/* Only beyond the standard three: 0, 1 and 2 are bound as the process's
|
|
19872
|
+
* terminal-or-pipe streams by the worker itself, and installing a second
|
|
19873
|
+
* stream over one of them would leave two objects claiming the number. */
|
|
19874
|
+
inheritFds: [...options.inherit?.keys() ?? []].filter((fd) => fd > 2)
|
|
19819
19875
|
});
|
|
19820
19876
|
return {
|
|
19821
19877
|
write: (data) => stdin.push(data),
|
|
@@ -20303,6 +20359,129 @@ raise SystemExit(entry())
|
|
|
20303
20359
|
}
|
|
20304
20360
|
|
|
20305
20361
|
// src/runtime/python/backend.ts
|
|
20362
|
+
var PENDING_INHERITANCE = /* @__PURE__ */ new Map();
|
|
20363
|
+
var INHERIT_TOKEN = "SBX_PYTHON_INHERIT";
|
|
20364
|
+
var WNOHANG = 1;
|
|
20365
|
+
function claimInheritance(env2) {
|
|
20366
|
+
const token = env2[INHERIT_TOKEN];
|
|
20367
|
+
if (!token) return void 0;
|
|
20368
|
+
const files = PENDING_INHERITANCE.get(token);
|
|
20369
|
+
PENDING_INHERITANCE.delete(token);
|
|
20370
|
+
delete env2[INHERIT_TOKEN];
|
|
20371
|
+
return files;
|
|
20372
|
+
}
|
|
20373
|
+
function waitStatus(proc) {
|
|
20374
|
+
if (proc.termSignal) return signalNumber(proc.termSignal) & 127;
|
|
20375
|
+
return ((proc.exitCode ?? 0) & 255) << 8;
|
|
20376
|
+
}
|
|
20377
|
+
function outputFor(description, fallback) {
|
|
20378
|
+
if (!description) return fallback;
|
|
20379
|
+
return {
|
|
20380
|
+
write(data) {
|
|
20381
|
+
description.write(typeof data === "string" ? new TextEncoder().encode(data) : data);
|
|
20382
|
+
},
|
|
20383
|
+
end() {
|
|
20384
|
+
},
|
|
20385
|
+
get closed() {
|
|
20386
|
+
return false;
|
|
20387
|
+
},
|
|
20388
|
+
isTTY: fallback.isTTY
|
|
20389
|
+
};
|
|
20390
|
+
}
|
|
20391
|
+
function createProcessService(ctx) {
|
|
20392
|
+
const children = /* @__PURE__ */ new Map();
|
|
20393
|
+
const exited = (proc) => proc.exitCode !== null || proc.termSignal !== null;
|
|
20394
|
+
return {
|
|
20395
|
+
async spawn(request) {
|
|
20396
|
+
const token = `${ctx.proc.pid}:${Math.random().toString(36).slice(2)}`;
|
|
20397
|
+
const env2 = { ...request.env };
|
|
20398
|
+
if (request.files.size > 0) {
|
|
20399
|
+
PENDING_INHERITANCE.set(token, new Map(request.files));
|
|
20400
|
+
env2[INHERIT_TOKEN] = token;
|
|
20401
|
+
}
|
|
20402
|
+
const stdin = request.files.get(0);
|
|
20403
|
+
const argv = [containerProgram(ctx, request.argv[0] ?? ""), ...request.argv.slice(1)];
|
|
20404
|
+
const proc = ctx.kernel.spawn(argv, {
|
|
20405
|
+
cwd: request.cwd,
|
|
20406
|
+
env: env2,
|
|
20407
|
+
cred: ctx.cred,
|
|
20408
|
+
ppid: ctx.proc.pid,
|
|
20409
|
+
stdin: stdin ? descriptionInput(stdin) : void 0,
|
|
20410
|
+
stdout: outputFor(request.files.get(1), ctx.stdout),
|
|
20411
|
+
stderr: outputFor(request.files.get(2), ctx.stderr)
|
|
20412
|
+
});
|
|
20413
|
+
children.set(proc.pid, proc);
|
|
20414
|
+
void proc.wait().finally(() => PENDING_INHERITANCE.delete(token));
|
|
20415
|
+
return proc.pid;
|
|
20416
|
+
},
|
|
20417
|
+
async wait(pid, options) {
|
|
20418
|
+
const candidates = pid > 0 ? [children.get(pid)].filter((p) => p !== void 0) : [...children.values()];
|
|
20419
|
+
if (candidates.length === 0) throw new PosixError(Errno.ECHILD);
|
|
20420
|
+
const reap = (proc) => {
|
|
20421
|
+
children.delete(proc.pid);
|
|
20422
|
+
return { pid: proc.pid, status: waitStatus(proc) };
|
|
20423
|
+
};
|
|
20424
|
+
const done = candidates.find(exited);
|
|
20425
|
+
if (done) return reap(done);
|
|
20426
|
+
if (options & WNOHANG) return { pid: 0, status: 0 };
|
|
20427
|
+
await Promise.race(candidates.map((proc) => proc.wait()));
|
|
20428
|
+
const finished = candidates.find(exited);
|
|
20429
|
+
if (!finished) throw new PosixError(Errno.ECHILD);
|
|
20430
|
+
return reap(finished);
|
|
20431
|
+
},
|
|
20432
|
+
kill(pid, signal) {
|
|
20433
|
+
const proc = children.get(pid) ?? ctx.kernel.procs.get(pid);
|
|
20434
|
+
if (!proc) throw new PosixError(Errno.ESRCH);
|
|
20435
|
+
if (signal === 0) return;
|
|
20436
|
+
const name = SIGNAL_NAMES[signal];
|
|
20437
|
+
if (!name) throw new PosixError(Errno.EINVAL);
|
|
20438
|
+
proc.deliver(name);
|
|
20439
|
+
}
|
|
20440
|
+
};
|
|
20441
|
+
}
|
|
20442
|
+
function containerProgram(ctx, program) {
|
|
20443
|
+
const resolvable = (name) => name !== "" && ctx.kernel.resolveExecutable(name, ctx.cwd, ctx.env, ctx.cred) !== null;
|
|
20444
|
+
if (resolvable(program)) return program;
|
|
20445
|
+
const base2 = program.slice(program.lastIndexOf("/") + 1);
|
|
20446
|
+
if (resolvable(base2)) return base2;
|
|
20447
|
+
if (base2.startsWith("python")) return "python3";
|
|
20448
|
+
return program;
|
|
20449
|
+
}
|
|
20450
|
+
function descriptionInput(description) {
|
|
20451
|
+
const read = async (size) => {
|
|
20452
|
+
for (; ; ) {
|
|
20453
|
+
try {
|
|
20454
|
+
const chunk = description.read(size);
|
|
20455
|
+
if (chunk.length === 0) return null;
|
|
20456
|
+
return chunk;
|
|
20457
|
+
} catch {
|
|
20458
|
+
await description.whenReady();
|
|
20459
|
+
}
|
|
20460
|
+
}
|
|
20461
|
+
};
|
|
20462
|
+
return {
|
|
20463
|
+
isTTY: false,
|
|
20464
|
+
interactive: false,
|
|
20465
|
+
read,
|
|
20466
|
+
async readAll() {
|
|
20467
|
+
const parts = [];
|
|
20468
|
+
for (; ; ) {
|
|
20469
|
+
const chunk = await read(65536);
|
|
20470
|
+
if (chunk === null) break;
|
|
20471
|
+
parts.push(chunk);
|
|
20472
|
+
}
|
|
20473
|
+
let total = 0;
|
|
20474
|
+
for (const part of parts) total += part.length;
|
|
20475
|
+
const out = new Uint8Array(total);
|
|
20476
|
+
let at = 0;
|
|
20477
|
+
for (const part of parts) {
|
|
20478
|
+
out.set(part, at);
|
|
20479
|
+
at += part.length;
|
|
20480
|
+
}
|
|
20481
|
+
return out;
|
|
20482
|
+
}
|
|
20483
|
+
};
|
|
20484
|
+
}
|
|
20306
20485
|
function withSitePackages(env2) {
|
|
20307
20486
|
const existing = env2.PYTHONPATH;
|
|
20308
20487
|
return {
|
|
@@ -20343,6 +20522,8 @@ async function runOwnedPython(ctx, argv) {
|
|
|
20343
20522
|
const { manifest, workerUrl } = pythonBackend();
|
|
20344
20523
|
if (!manifest) throw new Error("no Python runtime manifest is configured");
|
|
20345
20524
|
const mounts = containerMounts(ctx);
|
|
20525
|
+
const env2 = withSitePackages(ctx.env);
|
|
20526
|
+
const inherit = claimInheritance(env2);
|
|
20346
20527
|
const process2 = await startPythonProcess({
|
|
20347
20528
|
manifest,
|
|
20348
20529
|
workerUrl: await resolveWorkerUrl(workerUrl),
|
|
@@ -20351,14 +20532,16 @@ async function runOwnedPython(ctx, argv) {
|
|
|
20351
20532
|
pid: ctx.proc.pid,
|
|
20352
20533
|
ppid: ctx.proc.ppid ?? 1,
|
|
20353
20534
|
argv,
|
|
20354
|
-
env:
|
|
20535
|
+
env: env2,
|
|
20355
20536
|
cwd: ctx.cwd,
|
|
20356
20537
|
isTty: isTerminal(ctx),
|
|
20357
20538
|
mounts,
|
|
20358
20539
|
onStdout: (data) => ctx.stdout.write(data),
|
|
20359
20540
|
onStderr: (data) => ctx.stderr.write(data),
|
|
20360
20541
|
signal: ctx.signal,
|
|
20361
|
-
sockets: ctx.kernel.pod.sockets
|
|
20542
|
+
sockets: ctx.kernel.pod.sockets,
|
|
20543
|
+
processes: createProcessService(ctx),
|
|
20544
|
+
inherit
|
|
20362
20545
|
});
|
|
20363
20546
|
void pumpStdin(ctx, process2);
|
|
20364
20547
|
return process2.wait();
|