sandboxedjs 0.1.16 → 0.1.18
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 +28 -20
- package/dist/index.cjs +300 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -2
- package/dist/index.d.ts +50 -2
- package/dist/index.js +299 -12
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.d.cts
CHANGED
|
@@ -1298,7 +1298,20 @@ declare class Shell {
|
|
|
1298
1298
|
*/
|
|
1299
1299
|
|
|
1300
1300
|
declare const PYTHON_VERSION = "3.4.0";
|
|
1301
|
+
/**
|
|
1302
|
+
* Which interpreter `python3` is.
|
|
1303
|
+
*
|
|
1304
|
+
* `auto` prefers CPython and falls back to MicroPython, so a host that has not
|
|
1305
|
+
* installed Pyodide keeps working exactly as it did before.
|
|
1306
|
+
*/
|
|
1307
|
+
type PythonEngine = "auto" | "cpython" | "micropython";
|
|
1301
1308
|
interface PythonOptions {
|
|
1309
|
+
/** Interpreter to run. Defaults to `auto`. */
|
|
1310
|
+
engine?: PythonEngine;
|
|
1311
|
+
/** Where Pyodide's assets live; only a browser needs to say. */
|
|
1312
|
+
indexURL?: string;
|
|
1313
|
+
/** URL of the Pyodide ES module, for a browser with no bundler. */
|
|
1314
|
+
pyodideURL?: string;
|
|
1302
1315
|
/**
|
|
1303
1316
|
* Absolute URL of `micropython.wasm`.
|
|
1304
1317
|
*
|
|
@@ -1318,7 +1331,6 @@ interface PythonOptions {
|
|
|
1318
1331
|
*/
|
|
1319
1332
|
wasmUrl?: string;
|
|
1320
1333
|
}
|
|
1321
|
-
/** Point the Python runtime at its WebAssembly binary. */
|
|
1322
1334
|
declare function configurePython(options?: PythonOptions): void;
|
|
1323
1335
|
/** True when a Python interpreter can be started in this process. */
|
|
1324
1336
|
declare function isPythonAvailable(): Promise<boolean>;
|
|
@@ -2004,6 +2016,42 @@ declare function buildRootfs(vfs: Vfs, opts?: RootfsOptions): void;
|
|
|
2004
2016
|
|
|
2005
2017
|
declare const NODE_VERSION = "v22.12.0";
|
|
2006
2018
|
|
|
2019
|
+
/**
|
|
2020
|
+
* The CPython runtime: Pyodide, wired to the container the same way
|
|
2021
|
+
* MicroPython is — filesystem, argv, environment and standard streams.
|
|
2022
|
+
*
|
|
2023
|
+
* This is real CPython, so `sqlite3`, `dataclasses`, `decimal`, `typing` and
|
|
2024
|
+
* the rest of the standard library are present, and `micropip` can install
|
|
2025
|
+
* pure-Python wheels. MicroPython remains for hosts that do not want a 13 MB
|
|
2026
|
+
* interpreter: see `configurePython`.
|
|
2027
|
+
*
|
|
2028
|
+
* Two things differ from the MicroPython path, and both are forced by CPython
|
|
2029
|
+
* keeping its own library inside the Emscripten filesystem:
|
|
2030
|
+
*
|
|
2031
|
+
* - the container is mounted subtree by subtree rather than over `/`, so
|
|
2032
|
+
* `/lib/python314.zip` survives;
|
|
2033
|
+
* - an interpreter costs roughly a second and a half to start, so one is kept
|
|
2034
|
+
* per container and each program is run in a fresh namespace instead.
|
|
2035
|
+
*/
|
|
2036
|
+
|
|
2037
|
+
interface CPythonOptions {
|
|
2038
|
+
/**
|
|
2039
|
+
* Where Pyodide's own assets live.
|
|
2040
|
+
*
|
|
2041
|
+
* Node resolves them from the installed package, so this is only needed in a
|
|
2042
|
+
* browser, where they are served or taken from a CDN.
|
|
2043
|
+
*/
|
|
2044
|
+
indexURL?: string;
|
|
2045
|
+
/**
|
|
2046
|
+
* URL of the Pyodide ES module, for hosts that cannot resolve the package by
|
|
2047
|
+
* name — a browser without a bundler, typically.
|
|
2048
|
+
*/
|
|
2049
|
+
moduleURL?: string;
|
|
2050
|
+
}
|
|
2051
|
+
declare function configureCPython(options?: CPythonOptions): void;
|
|
2052
|
+
/** True when this host can start CPython at all. */
|
|
2053
|
+
declare function isCPythonAvailable(): Promise<boolean>;
|
|
2054
|
+
|
|
2007
2055
|
/**
|
|
2008
2056
|
* Package managers: `npm`/`npx`/`yarn`/`pnpm` on top of Nodepod's installer,
|
|
2009
2057
|
* and an `apt`-shaped front end for the things a container image would ship.
|
|
@@ -2029,4 +2077,4 @@ declare const NPM_VERSION = "10.9.0";
|
|
|
2029
2077
|
* ```
|
|
2030
2078
|
*/
|
|
2031
2079
|
|
|
2032
|
-
export { ArithError, BufferSink, CallbackSink, type Command, CommandRegistry, Container, ContainerFs, type ContainerOptions, type ContextInit, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, type VirtualNode, type VirtualProvider, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configurePython, createContainer, createContext, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
|
2080
|
+
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type Command, CommandRegistry, Container, ContainerFs, type ContainerOptions, type ContextInit, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonEngine, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, type VirtualNode, type VirtualProvider, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createContainer, createContext, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -1298,7 +1298,20 @@ declare class Shell {
|
|
|
1298
1298
|
*/
|
|
1299
1299
|
|
|
1300
1300
|
declare const PYTHON_VERSION = "3.4.0";
|
|
1301
|
+
/**
|
|
1302
|
+
* Which interpreter `python3` is.
|
|
1303
|
+
*
|
|
1304
|
+
* `auto` prefers CPython and falls back to MicroPython, so a host that has not
|
|
1305
|
+
* installed Pyodide keeps working exactly as it did before.
|
|
1306
|
+
*/
|
|
1307
|
+
type PythonEngine = "auto" | "cpython" | "micropython";
|
|
1301
1308
|
interface PythonOptions {
|
|
1309
|
+
/** Interpreter to run. Defaults to `auto`. */
|
|
1310
|
+
engine?: PythonEngine;
|
|
1311
|
+
/** Where Pyodide's assets live; only a browser needs to say. */
|
|
1312
|
+
indexURL?: string;
|
|
1313
|
+
/** URL of the Pyodide ES module, for a browser with no bundler. */
|
|
1314
|
+
pyodideURL?: string;
|
|
1302
1315
|
/**
|
|
1303
1316
|
* Absolute URL of `micropython.wasm`.
|
|
1304
1317
|
*
|
|
@@ -1318,7 +1331,6 @@ interface PythonOptions {
|
|
|
1318
1331
|
*/
|
|
1319
1332
|
wasmUrl?: string;
|
|
1320
1333
|
}
|
|
1321
|
-
/** Point the Python runtime at its WebAssembly binary. */
|
|
1322
1334
|
declare function configurePython(options?: PythonOptions): void;
|
|
1323
1335
|
/** True when a Python interpreter can be started in this process. */
|
|
1324
1336
|
declare function isPythonAvailable(): Promise<boolean>;
|
|
@@ -2004,6 +2016,42 @@ declare function buildRootfs(vfs: Vfs, opts?: RootfsOptions): void;
|
|
|
2004
2016
|
|
|
2005
2017
|
declare const NODE_VERSION = "v22.12.0";
|
|
2006
2018
|
|
|
2019
|
+
/**
|
|
2020
|
+
* The CPython runtime: Pyodide, wired to the container the same way
|
|
2021
|
+
* MicroPython is — filesystem, argv, environment and standard streams.
|
|
2022
|
+
*
|
|
2023
|
+
* This is real CPython, so `sqlite3`, `dataclasses`, `decimal`, `typing` and
|
|
2024
|
+
* the rest of the standard library are present, and `micropip` can install
|
|
2025
|
+
* pure-Python wheels. MicroPython remains for hosts that do not want a 13 MB
|
|
2026
|
+
* interpreter: see `configurePython`.
|
|
2027
|
+
*
|
|
2028
|
+
* Two things differ from the MicroPython path, and both are forced by CPython
|
|
2029
|
+
* keeping its own library inside the Emscripten filesystem:
|
|
2030
|
+
*
|
|
2031
|
+
* - the container is mounted subtree by subtree rather than over `/`, so
|
|
2032
|
+
* `/lib/python314.zip` survives;
|
|
2033
|
+
* - an interpreter costs roughly a second and a half to start, so one is kept
|
|
2034
|
+
* per container and each program is run in a fresh namespace instead.
|
|
2035
|
+
*/
|
|
2036
|
+
|
|
2037
|
+
interface CPythonOptions {
|
|
2038
|
+
/**
|
|
2039
|
+
* Where Pyodide's own assets live.
|
|
2040
|
+
*
|
|
2041
|
+
* Node resolves them from the installed package, so this is only needed in a
|
|
2042
|
+
* browser, where they are served or taken from a CDN.
|
|
2043
|
+
*/
|
|
2044
|
+
indexURL?: string;
|
|
2045
|
+
/**
|
|
2046
|
+
* URL of the Pyodide ES module, for hosts that cannot resolve the package by
|
|
2047
|
+
* name — a browser without a bundler, typically.
|
|
2048
|
+
*/
|
|
2049
|
+
moduleURL?: string;
|
|
2050
|
+
}
|
|
2051
|
+
declare function configureCPython(options?: CPythonOptions): void;
|
|
2052
|
+
/** True when this host can start CPython at all. */
|
|
2053
|
+
declare function isCPythonAvailable(): Promise<boolean>;
|
|
2054
|
+
|
|
2007
2055
|
/**
|
|
2008
2056
|
* Package managers: `npm`/`npx`/`yarn`/`pnpm` on top of Nodepod's installer,
|
|
2009
2057
|
* and an `apt`-shaped front end for the things a container image would ship.
|
|
@@ -2029,4 +2077,4 @@ declare const NPM_VERSION = "10.9.0";
|
|
|
2029
2077
|
* ```
|
|
2030
2078
|
*/
|
|
2031
2079
|
|
|
2032
|
-
export { ArithError, BufferSink, CallbackSink, type Command, CommandRegistry, Container, ContainerFs, type ContainerOptions, type ContextInit, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, type VirtualNode, type VirtualProvider, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configurePython, createContainer, createContext, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
|
2080
|
+
export { ArithError, BufferSink, type CPythonOptions, CallbackSink, type Command, CommandRegistry, Container, ContainerFs, type ContainerOptions, type ContextInit, type Cred, type DirEntry, ERRNO, type Env, type ErrnoCode, type ExecContext, type ExecOptions, type ExecResult, type FileData, FileInput, FileOutput, type GroupEntry, type HttpResponse, IncompleteInputError, type InputStream, type Job, KERNEL_NAME, KERNEL_RELEASE, Kernel, type KernelOptions, type ListeningPort, type MountEntry, NODE_VERSION, NPM_VERSION, type NetInterface, type NetworkOptions, NetworkStack, NullInput, NullOutput, OS_RELEASE, type OutputStream, PYTHON_VERSION, type PasswdEntry, Pipe, Process, type ProcessKind, type ProcessOptions, type ProcessState, ProcessTable, type PythonEngine, type PythonOptions, ROOT_CRED, type ResolvedExecutable, type RootfsOptions, type RunOptions, type RunResult, SIGNALS, SIGNAL_NAMES, Session, type SessionInit, type SessionResult, type SessionRunOptions, Shell, ShellExit, type ShellIO, type ShellInit, Lexer as ShellLexer, type ShellOptions, ShellSyntaxError, type SpawnHandle, Stats, type Stdio, SysError, TeeOutput, Terminal, type TerminalOptions, UserDatabase, Variables, Vfs, type VirtualNode, type VirtualProvider, type WriteOptions, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createContainer, createContext, createContainer as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
package/dist/index.js
CHANGED
|
@@ -21936,6 +21936,7 @@ function mountContainerFs(FS, opts) {
|
|
|
21936
21936
|
if (isSysError(e)) return throwErrno(e.code);
|
|
21937
21937
|
throw new FS.ErrnoError(emErrno("EIO"));
|
|
21938
21938
|
};
|
|
21939
|
+
const mountRoot = opts.mountAt ? normalize(opts.mountAt) : "/";
|
|
21939
21940
|
const backend = {
|
|
21940
21941
|
/** Absolute container path for a node. */
|
|
21941
21942
|
realPath(node2) {
|
|
@@ -21945,7 +21946,9 @@ function mountContainerFs(FS, opts) {
|
|
|
21945
21946
|
parts.unshift(current.name);
|
|
21946
21947
|
current = current.parent;
|
|
21947
21948
|
}
|
|
21948
|
-
|
|
21949
|
+
const relative2 = parts.join("/");
|
|
21950
|
+
if (mountRoot === "/") return "/" + relative2;
|
|
21951
|
+
return relative2 ? join(mountRoot, relative2) : mountRoot;
|
|
21949
21952
|
},
|
|
21950
21953
|
mount(_mount) {
|
|
21951
21954
|
return backend.createNode(null, "/", 16877 | 0, 0);
|
|
@@ -22135,6 +22138,14 @@ function mountContainerFs(FS, opts) {
|
|
|
22135
22138
|
return position;
|
|
22136
22139
|
}
|
|
22137
22140
|
};
|
|
22141
|
+
if (opts.mountAt) {
|
|
22142
|
+
try {
|
|
22143
|
+
FS.mkdir(mountRoot);
|
|
22144
|
+
} catch {
|
|
22145
|
+
}
|
|
22146
|
+
FS.mount(backend, {}, mountRoot);
|
|
22147
|
+
return;
|
|
22148
|
+
}
|
|
22138
22149
|
FS.root = null;
|
|
22139
22150
|
FS.mount(backend, {}, "/");
|
|
22140
22151
|
try {
|
|
@@ -22143,13 +22154,286 @@ function mountContainerFs(FS, opts) {
|
|
|
22143
22154
|
}
|
|
22144
22155
|
}
|
|
22145
22156
|
|
|
22157
|
+
// src/runtime/cpython.ts
|
|
22158
|
+
var RESERVED_FOR_INTERPRETER = /* @__PURE__ */ new Set(["lib", "dev", "proc"]);
|
|
22159
|
+
var pyodideModule = null;
|
|
22160
|
+
var indexUrl;
|
|
22161
|
+
var moduleUrl;
|
|
22162
|
+
function configureCPython(options = {}) {
|
|
22163
|
+
if (options.indexURL !== void 0) indexUrl = options.indexURL;
|
|
22164
|
+
if (options.moduleURL !== void 0) {
|
|
22165
|
+
moduleUrl = options.moduleURL;
|
|
22166
|
+
pyodideModule = null;
|
|
22167
|
+
}
|
|
22168
|
+
}
|
|
22169
|
+
function importPyodide() {
|
|
22170
|
+
if (!pyodideModule) {
|
|
22171
|
+
const specifier = moduleUrl ?? ["py", "odide"].join("");
|
|
22172
|
+
pyodideModule = import(
|
|
22173
|
+
/* @vite-ignore */
|
|
22174
|
+
/* webpackIgnore: true */
|
|
22175
|
+
specifier
|
|
22176
|
+
);
|
|
22177
|
+
}
|
|
22178
|
+
return pyodideModule;
|
|
22179
|
+
}
|
|
22180
|
+
var isNode2 = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
22181
|
+
async function resolveIndexUrl() {
|
|
22182
|
+
if (indexUrl) return indexUrl;
|
|
22183
|
+
if (!isNode2) return void 0;
|
|
22184
|
+
try {
|
|
22185
|
+
const { createRequire } = await nodeBuiltin("module");
|
|
22186
|
+
const path = await nodeBuiltin("path");
|
|
22187
|
+
const require2 = createRequire(path.join(process.cwd(), "index.js"));
|
|
22188
|
+
return `${path.dirname(require2.resolve("pyodide/package.json"))}/`;
|
|
22189
|
+
} catch {
|
|
22190
|
+
return void 0;
|
|
22191
|
+
}
|
|
22192
|
+
}
|
|
22193
|
+
async function isCPythonAvailable() {
|
|
22194
|
+
try {
|
|
22195
|
+
await importPyodide();
|
|
22196
|
+
return true;
|
|
22197
|
+
} catch {
|
|
22198
|
+
return false;
|
|
22199
|
+
}
|
|
22200
|
+
}
|
|
22201
|
+
var interpreters = /* @__PURE__ */ new WeakMap();
|
|
22202
|
+
async function interpreterFor(ctx) {
|
|
22203
|
+
const existing = interpreters.get(ctx.vfs);
|
|
22204
|
+
if (existing) return existing;
|
|
22205
|
+
const starting = (async () => {
|
|
22206
|
+
const { loadPyodide } = await importPyodide();
|
|
22207
|
+
const resolved = await resolveIndexUrl();
|
|
22208
|
+
const py = await loadPyodide({
|
|
22209
|
+
...resolved ? { indexURL: resolved } : {},
|
|
22210
|
+
/* Output is rebound per program; these only catch anything printed
|
|
22211
|
+
* while the interpreter is still starting. */
|
|
22212
|
+
stdout: () => {
|
|
22213
|
+
},
|
|
22214
|
+
stderr: () => {
|
|
22215
|
+
}
|
|
22216
|
+
});
|
|
22217
|
+
mountContainerDirs(py, ctx);
|
|
22218
|
+
installRunner(py);
|
|
22219
|
+
return py;
|
|
22220
|
+
})();
|
|
22221
|
+
interpreters.set(ctx.vfs, starting);
|
|
22222
|
+
try {
|
|
22223
|
+
return await starting;
|
|
22224
|
+
} catch (error) {
|
|
22225
|
+
interpreters.delete(ctx.vfs);
|
|
22226
|
+
throw error;
|
|
22227
|
+
}
|
|
22228
|
+
}
|
|
22229
|
+
function installRunner(py) {
|
|
22230
|
+
py.__sbxRun = py.runPython(`
|
|
22231
|
+
from pyodide.code import eval_code_async
|
|
22232
|
+
|
|
22233
|
+
async def __sbx_run(source, scope):
|
|
22234
|
+
try:
|
|
22235
|
+
await eval_code_async(source, globals=scope)
|
|
22236
|
+
return 0
|
|
22237
|
+
except SystemExit as exit:
|
|
22238
|
+
code = exit.code
|
|
22239
|
+
if code is None:
|
|
22240
|
+
return 0
|
|
22241
|
+
return code if isinstance(code, int) else 1
|
|
22242
|
+
|
|
22243
|
+
__sbx_run
|
|
22244
|
+
`);
|
|
22245
|
+
}
|
|
22246
|
+
function mountContainerDirs(py, ctx) {
|
|
22247
|
+
const mounted = py.__sbxMounted ??= /* @__PURE__ */ new Set();
|
|
22248
|
+
let entries;
|
|
22249
|
+
try {
|
|
22250
|
+
entries = ctx.vfs.readdirWithTypes("/", ctx.cred);
|
|
22251
|
+
} catch {
|
|
22252
|
+
return;
|
|
22253
|
+
}
|
|
22254
|
+
for (const entry of entries) {
|
|
22255
|
+
if (entry.kind !== "directory") continue;
|
|
22256
|
+
if (RESERVED_FOR_INTERPRETER.has(entry.name)) continue;
|
|
22257
|
+
if (mounted.has(entry.name)) continue;
|
|
22258
|
+
try {
|
|
22259
|
+
mountContainerFs(py.FS, {
|
|
22260
|
+
vfs: ctx.vfs,
|
|
22261
|
+
cred: ctx.cred,
|
|
22262
|
+
mountAt: `/${entry.name}`
|
|
22263
|
+
});
|
|
22264
|
+
mounted.add(entry.name);
|
|
22265
|
+
} catch {
|
|
22266
|
+
}
|
|
22267
|
+
}
|
|
22268
|
+
}
|
|
22269
|
+
function bootstrap(py, ctx, argv, scriptDir) {
|
|
22270
|
+
const paths = [
|
|
22271
|
+
...scriptDir ? [scriptDir] : [""],
|
|
22272
|
+
"/usr/lib/python3",
|
|
22273
|
+
"/usr/lib/python3/site-packages",
|
|
22274
|
+
"/usr/local/lib/python3/site-packages"
|
|
22275
|
+
];
|
|
22276
|
+
py.runPython(`
|
|
22277
|
+
import sys, os
|
|
22278
|
+
sys.argv[:] = ${JSON.stringify(argv)}
|
|
22279
|
+
for __p in reversed(${JSON.stringify(paths)}):
|
|
22280
|
+
if __p and __p not in sys.path:
|
|
22281
|
+
sys.path.insert(0, __p)
|
|
22282
|
+
elif __p == "" and "" not in sys.path:
|
|
22283
|
+
sys.path.insert(0, "")
|
|
22284
|
+
try:
|
|
22285
|
+
del __p
|
|
22286
|
+
except NameError:
|
|
22287
|
+
pass
|
|
22288
|
+
os.environ.clear()
|
|
22289
|
+
os.environ.update(${JSON.stringify(ctx.env)})
|
|
22290
|
+
`);
|
|
22291
|
+
try {
|
|
22292
|
+
py.FS.chdir(ctx.cwd);
|
|
22293
|
+
} catch {
|
|
22294
|
+
}
|
|
22295
|
+
}
|
|
22296
|
+
function reportError(ctx, error) {
|
|
22297
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
22298
|
+
const systemExit = /SystemExit:?\s*(-?\d+)?/.exec(message);
|
|
22299
|
+
if (systemExit) {
|
|
22300
|
+
return systemExit[1] !== void 0 ? Number(systemExit[1]) & 255 : 0;
|
|
22301
|
+
}
|
|
22302
|
+
if (/KeyboardInterrupt/.test(message)) {
|
|
22303
|
+
ctx.stderr.write("KeyboardInterrupt\n");
|
|
22304
|
+
return 130;
|
|
22305
|
+
}
|
|
22306
|
+
const text = message.replace(/^PythonError:\s*/, "");
|
|
22307
|
+
ctx.stderr.write(text.endsWith("\n") ? text : `${text}
|
|
22308
|
+
`);
|
|
22309
|
+
return 1;
|
|
22310
|
+
}
|
|
22311
|
+
async function runCPythonProgram(ctx, source, argv, scriptDir, stdinText) {
|
|
22312
|
+
let py;
|
|
22313
|
+
try {
|
|
22314
|
+
py = await interpreterFor(ctx);
|
|
22315
|
+
} catch (error) {
|
|
22316
|
+
ctx.stderr.write(
|
|
22317
|
+
`python3: CPython is unavailable in this host (${error instanceof Error ? error.message : String(error)})
|
|
22318
|
+
`
|
|
22319
|
+
);
|
|
22320
|
+
return { exitCode: 127 };
|
|
22321
|
+
}
|
|
22322
|
+
mountContainerDirs(py, ctx);
|
|
22323
|
+
try {
|
|
22324
|
+
await py.loadPackagesFromImports(source, {
|
|
22325
|
+
messageCallback: () => {
|
|
22326
|
+
},
|
|
22327
|
+
errorCallback: () => {
|
|
22328
|
+
}
|
|
22329
|
+
});
|
|
22330
|
+
} catch {
|
|
22331
|
+
}
|
|
22332
|
+
const encoder6 = new TextEncoder();
|
|
22333
|
+
const decoder7 = new TextDecoder();
|
|
22334
|
+
py.setStdout({
|
|
22335
|
+
write: (buffer) => {
|
|
22336
|
+
ctx.write(decoder7.decode(buffer));
|
|
22337
|
+
return buffer.length;
|
|
22338
|
+
}
|
|
22339
|
+
});
|
|
22340
|
+
py.setStderr({
|
|
22341
|
+
write: (buffer) => {
|
|
22342
|
+
ctx.stderr.write(decoder7.decode(buffer));
|
|
22343
|
+
return buffer.length;
|
|
22344
|
+
}
|
|
22345
|
+
});
|
|
22346
|
+
if (stdinText !== null) {
|
|
22347
|
+
const bytes = encoder6.encode(stdinText);
|
|
22348
|
+
let offset = 0;
|
|
22349
|
+
py.setStdin({
|
|
22350
|
+
read: (buffer) => {
|
|
22351
|
+
const take = Math.min(buffer.length, bytes.length - offset);
|
|
22352
|
+
buffer.set(bytes.subarray(offset, offset + take));
|
|
22353
|
+
offset += take;
|
|
22354
|
+
return take;
|
|
22355
|
+
}
|
|
22356
|
+
});
|
|
22357
|
+
} else {
|
|
22358
|
+
py.setStdin({ read: () => 0 });
|
|
22359
|
+
}
|
|
22360
|
+
try {
|
|
22361
|
+
bootstrap(py, ctx, argv, scriptDir);
|
|
22362
|
+
} catch (error) {
|
|
22363
|
+
return { exitCode: reportError(ctx, error) };
|
|
22364
|
+
}
|
|
22365
|
+
const globals = py.globals.get("dict")();
|
|
22366
|
+
try {
|
|
22367
|
+
globals.set("__name__", "__main__");
|
|
22368
|
+
const exitCode = await py.__sbxRun(source, globals);
|
|
22369
|
+
return { exitCode: Number(exitCode) & 255 };
|
|
22370
|
+
} catch (error) {
|
|
22371
|
+
return { exitCode: reportError(ctx, error) };
|
|
22372
|
+
} finally {
|
|
22373
|
+
try {
|
|
22374
|
+
globals.destroy();
|
|
22375
|
+
} catch {
|
|
22376
|
+
}
|
|
22377
|
+
}
|
|
22378
|
+
}
|
|
22379
|
+
var micropip = defineCommand({
|
|
22380
|
+
name: "micropip",
|
|
22381
|
+
path: "/usr/bin/micropip",
|
|
22382
|
+
summary: "install Python packages into the running interpreter",
|
|
22383
|
+
usage: "micropip install <package>...",
|
|
22384
|
+
async run(ctx) {
|
|
22385
|
+
const [action, ...packages] = ctx.args;
|
|
22386
|
+
if (action !== "install" || packages.length === 0) {
|
|
22387
|
+
ctx.line("usage: micropip install <package>...");
|
|
22388
|
+
return action === void 0 ? 1 : 0;
|
|
22389
|
+
}
|
|
22390
|
+
let py;
|
|
22391
|
+
try {
|
|
22392
|
+
py = await interpreterFor(ctx);
|
|
22393
|
+
} catch {
|
|
22394
|
+
ctx.stderr.write("micropip: CPython is unavailable in this host\n");
|
|
22395
|
+
return 127;
|
|
22396
|
+
}
|
|
22397
|
+
try {
|
|
22398
|
+
await py.loadPackage("micropip");
|
|
22399
|
+
const micropipModule = py.pyimport("micropip");
|
|
22400
|
+
for (const name of packages) {
|
|
22401
|
+
ctx.line(`Collecting ${name}`);
|
|
22402
|
+
await micropipModule.install(name);
|
|
22403
|
+
ctx.line(`Successfully installed ${name}`);
|
|
22404
|
+
}
|
|
22405
|
+
return 0;
|
|
22406
|
+
} catch (error) {
|
|
22407
|
+
ctx.stderr.write(
|
|
22408
|
+
`micropip: ${error instanceof Error ? error.message : String(error)}
|
|
22409
|
+
`
|
|
22410
|
+
);
|
|
22411
|
+
return 1;
|
|
22412
|
+
}
|
|
22413
|
+
}
|
|
22414
|
+
});
|
|
22415
|
+
|
|
22146
22416
|
// src/runtime/python.ts
|
|
22147
22417
|
init_path();
|
|
22148
22418
|
var PYTHON_VERSION = "3.4.0";
|
|
22149
22419
|
var MICROPYTHON_BANNER = "MicroPython v1.28.0 on 2026-04-06; SandboxedJS with Emscripten";
|
|
22150
22420
|
var loaderPromise = null;
|
|
22151
22421
|
var wasmUrl;
|
|
22422
|
+
var engine = "auto";
|
|
22423
|
+
var cpythonUsable = null;
|
|
22424
|
+
async function useCPython() {
|
|
22425
|
+
if (engine === "micropython") return false;
|
|
22426
|
+
if (engine === "cpython") return true;
|
|
22427
|
+
cpythonUsable ??= isCPythonAvailable();
|
|
22428
|
+
return cpythonUsable;
|
|
22429
|
+
}
|
|
22152
22430
|
function configurePython(options = {}) {
|
|
22431
|
+
if (options.engine !== void 0) {
|
|
22432
|
+
engine = options.engine;
|
|
22433
|
+
cpythonUsable = null;
|
|
22434
|
+
}
|
|
22435
|
+
if (options.indexURL !== void 0) configureCPython({ indexURL: options.indexURL });
|
|
22436
|
+
if (options.pyodideURL !== void 0) configureCPython({ moduleURL: options.pyodideURL });
|
|
22153
22437
|
if (options.wasmUrl !== void 0) wasmUrl = options.wasmUrl;
|
|
22154
22438
|
}
|
|
22155
22439
|
async function getLoader() {
|
|
@@ -22224,6 +22508,9 @@ function reportPythonError(ctx, e) {
|
|
|
22224
22508
|
return 1;
|
|
22225
22509
|
}
|
|
22226
22510
|
async function runProgram(ctx, source, argv, scriptDir, stdinText) {
|
|
22511
|
+
if (await useCPython()) {
|
|
22512
|
+
return runCPythonProgram(ctx, source, argv, scriptDir, stdinText);
|
|
22513
|
+
}
|
|
22227
22514
|
let stdinOffset = 0;
|
|
22228
22515
|
const stdinBytes = stdinText === null ? new Uint8Array(0) : new TextEncoder().encode(stdinText);
|
|
22229
22516
|
const mp = await createInterpreter(ctx, {
|
|
@@ -22546,7 +22833,7 @@ async function readZip(data) {
|
|
|
22546
22833
|
return entries;
|
|
22547
22834
|
}
|
|
22548
22835
|
function pythonCommands() {
|
|
22549
|
-
return [python, pip];
|
|
22836
|
+
return [python, pip, micropip];
|
|
22550
22837
|
}
|
|
22551
22838
|
|
|
22552
22839
|
// src/runtime/ffmpeg.ts
|
|
@@ -22775,8 +23062,8 @@ function renameShadowedExports(source) {
|
|
|
22775
23062
|
for (const [key, value] of Object.entries(node2)) {
|
|
22776
23063
|
if (key === "type" || key === "start" || key === "end" || skip.includes(key)) continue;
|
|
22777
23064
|
if (Array.isArray(value)) {
|
|
22778
|
-
for (const item of value) if (
|
|
22779
|
-
} else if (
|
|
23065
|
+
for (const item of value) if (isNode3(item)) visit(item, childScope);
|
|
23066
|
+
} else if (isNode3(value)) {
|
|
22780
23067
|
visit(value, childScope);
|
|
22781
23068
|
}
|
|
22782
23069
|
}
|
|
@@ -22800,9 +23087,9 @@ function blockNames(body) {
|
|
|
22800
23087
|
for (const declarator of node2.declarations) {
|
|
22801
23088
|
collectPattern(declarator.id, names);
|
|
22802
23089
|
}
|
|
22803
|
-
} else if (node2.type === "ClassDeclaration" &&
|
|
23090
|
+
} else if (node2.type === "ClassDeclaration" && isNode3(node2.id)) {
|
|
22804
23091
|
names.add(node2.id.name);
|
|
22805
|
-
} else if (node2.type === "FunctionDeclaration" &&
|
|
23092
|
+
} else if (node2.type === "FunctionDeclaration" && isNode3(node2.id)) {
|
|
22806
23093
|
names.add(node2.id.name);
|
|
22807
23094
|
}
|
|
22808
23095
|
}
|
|
@@ -22813,10 +23100,10 @@ function collectVars(nodes, names) {
|
|
|
22813
23100
|
for (const item of nodes) collectVars(item, names);
|
|
22814
23101
|
return;
|
|
22815
23102
|
}
|
|
22816
|
-
if (!
|
|
23103
|
+
if (!isNode3(nodes)) return;
|
|
22817
23104
|
const node2 = nodes;
|
|
22818
23105
|
if (node2.type === "FunctionDeclaration" || node2.type === "FunctionExpression" || node2.type === "ArrowFunctionExpression") {
|
|
22819
|
-
if (
|
|
23106
|
+
if (isNode3(node2.id)) names.add(node2.id.name);
|
|
22820
23107
|
return;
|
|
22821
23108
|
}
|
|
22822
23109
|
if (node2.type === "VariableDeclaration" && node2.kind === "var") {
|
|
@@ -22830,7 +23117,7 @@ function collectVars(nodes, names) {
|
|
|
22830
23117
|
}
|
|
22831
23118
|
}
|
|
22832
23119
|
function collectPattern(node2, names) {
|
|
22833
|
-
if (!
|
|
23120
|
+
if (!isNode3(node2)) return;
|
|
22834
23121
|
switch (node2.type) {
|
|
22835
23122
|
case "Identifier":
|
|
22836
23123
|
names.add(node2.name);
|
|
@@ -22854,7 +23141,7 @@ function collectPattern(node2, names) {
|
|
|
22854
23141
|
}
|
|
22855
23142
|
}
|
|
22856
23143
|
function isExports(value) {
|
|
22857
|
-
return
|
|
23144
|
+
return isNode3(value) && value.type === "Identifier" && value.name === NAME;
|
|
22858
23145
|
}
|
|
22859
23146
|
function freshName(source) {
|
|
22860
23147
|
let name = "__sandboxedjs_exports";
|
|
@@ -22862,7 +23149,7 @@ function freshName(source) {
|
|
|
22862
23149
|
while (source.includes(name)) name = `__sandboxedjs_exports${++suffix}`;
|
|
22863
23150
|
return name;
|
|
22864
23151
|
}
|
|
22865
|
-
function
|
|
23152
|
+
function isNode3(value) {
|
|
22866
23153
|
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
22867
23154
|
}
|
|
22868
23155
|
var NOTHING = [];
|
|
@@ -24775,6 +25062,6 @@ init_expand();
|
|
|
24775
25062
|
init_builtins();
|
|
24776
25063
|
var src_default = createContainer;
|
|
24777
25064
|
|
|
24778
|
-
export { ArithError, BufferSink, CallbackSink, CommandRegistry, Container, ContainerFs, ERRNO, FileInput, FileOutput, IncompleteInputError, KERNEL_NAME, KERNEL_RELEASE, Kernel, NODE_VERSION, NPM_VERSION, NetworkStack, NullInput, NullOutput, OS_RELEASE, PYTHON_VERSION, Pipe, Process, ProcessTable, ROOT_CRED, SIGNALS, SIGNAL_NAMES, Session, Shell, ShellExit, Lexer as ShellLexer, ShellSyntaxError, Stats, SysError, TeeOutput, Terminal, UserDatabase, Variables, Vfs, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configurePython, createContainer, createContext, src_default as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path_exports as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
|
25065
|
+
export { ArithError, BufferSink, CallbackSink, CommandRegistry, Container, ContainerFs, ERRNO, FileInput, FileOutput, IncompleteInputError, KERNEL_NAME, KERNEL_RELEASE, Kernel, NODE_VERSION, NPM_VERSION, NetworkStack, NullInput, NullOutput, OS_RELEASE, PYTHON_VERSION, Pipe, Process, ProcessTable, ROOT_CRED, SIGNALS, SIGNAL_NAMES, Session, Shell, ShellExit, Lexer as ShellLexer, ShellSyntaxError, Stats, SysError, TeeOutput, Terminal, UserDatabase, Variables, Vfs, allCommands, applyChmod, braceExpand, buildRootfs, builtinNames, captureStdio, configureCPython, configurePython, createContainer, createContext, src_default as default, defineCommand, evalArith, exitCodeForSignal, expandPrompt, expandWord, expandWords, fnmatch, formatMode, getBuiltin, glob, globToRegex, hasMagic, installUserland, isBuiltinName, isCPythonAvailable, isPythonAvailable, isSysError, makeCred, normalizeSignal, octalMode, parse as parseShell, parseUmask, path_exports as posixPath, resetPidCounter, shellQuote, strerror, unameInfo };
|
|
24779
25066
|
//# sourceMappingURL=index.js.map
|
|
24780
25067
|
//# sourceMappingURL=index.js.map
|