sandboxedjs 0.1.12 → 0.1.13

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 CHANGED
@@ -23675,6 +23675,146 @@ var Session = class {
23675
23675
  }
23676
23676
  };
23677
23677
 
23678
+ // src/runtime/node-child-process-bridge.ts
23679
+ var KernelChildProcess = class {
23680
+ pid;
23681
+ command;
23682
+ args;
23683
+ parentPid;
23684
+ state = "running";
23685
+ exitCode;
23686
+ stdout = "";
23687
+ stderr = "";
23688
+ listeners = /* @__PURE__ */ new Map();
23689
+ kernel;
23690
+ cred;
23691
+ cwd;
23692
+ env;
23693
+ stdin = new Pipe();
23694
+ process;
23695
+ started = false;
23696
+ cancelled = false;
23697
+ constructor(kernel, cred, config, pid) {
23698
+ this.kernel = kernel;
23699
+ this.cred = cred;
23700
+ this.pid = pid;
23701
+ this.command = config.command;
23702
+ this.args = config.args?.slice() ?? [];
23703
+ this.parentPid = config.parentPid;
23704
+ this.cwd = config.cwd ?? "/";
23705
+ this.env = { ...config.env };
23706
+ }
23707
+ on(event, listener) {
23708
+ let listeners = this.listeners.get(event);
23709
+ if (!listeners) {
23710
+ listeners = /* @__PURE__ */ new Set();
23711
+ this.listeners.set(event, listeners);
23712
+ }
23713
+ listeners.add(listener);
23714
+ return this;
23715
+ }
23716
+ emit(event, ...args) {
23717
+ for (const listener of this.listeners.get(event) ?? []) listener(...args);
23718
+ }
23719
+ exec() {
23720
+ if (this.started) return;
23721
+ this.started = true;
23722
+ queueMicrotask(() => {
23723
+ if (this.cancelled) {
23724
+ this.finish(143);
23725
+ return;
23726
+ }
23727
+ const stdout = new ChildOutput(this, "stdout");
23728
+ const stderr = new ChildOutput(this, "stderr");
23729
+ try {
23730
+ this.process = this.kernel.spawn([this.command, ...this.args], {
23731
+ cwd: this.cwd,
23732
+ env: this.env,
23733
+ cred: this.cred,
23734
+ stdin: this.stdin,
23735
+ stdout,
23736
+ stderr,
23737
+ ppid: 1
23738
+ });
23739
+ void this.process.wait().then((code) => {
23740
+ stdout.end();
23741
+ stderr.end();
23742
+ this.finish(code);
23743
+ });
23744
+ } catch (error) {
23745
+ stderr.write(error instanceof Error ? error.message : String(error));
23746
+ stderr.end();
23747
+ stdout.end();
23748
+ this.finish(1);
23749
+ }
23750
+ });
23751
+ }
23752
+ sendStdin(data) {
23753
+ try {
23754
+ this.stdin.write(data);
23755
+ } catch {
23756
+ }
23757
+ }
23758
+ kill(signal = "SIGTERM") {
23759
+ if (this.process) {
23760
+ this.process.deliver(signal);
23761
+ return;
23762
+ }
23763
+ this.cancelled = true;
23764
+ }
23765
+ finish(code) {
23766
+ if (this.state === "exited") return;
23767
+ this.state = "exited";
23768
+ this.exitCode = code;
23769
+ this.emit("exit", code);
23770
+ }
23771
+ append(stream, text) {
23772
+ this[stream] += text;
23773
+ this.emit(stream, text);
23774
+ }
23775
+ };
23776
+ var ChildOutput = class {
23777
+ constructor(child, stream) {
23778
+ this.child = child;
23779
+ this.stream = stream;
23780
+ }
23781
+ child;
23782
+ stream;
23783
+ isTTY = false;
23784
+ closedState = false;
23785
+ decoder = new TextDecoder();
23786
+ get closed() {
23787
+ return this.closedState;
23788
+ }
23789
+ write(data) {
23790
+ if (this.closedState) return;
23791
+ const text = typeof data === "string" ? data : this.decoder.decode(data, { stream: true });
23792
+ if (text) this.child.append(this.stream, text);
23793
+ }
23794
+ end() {
23795
+ if (this.closedState) return;
23796
+ this.closedState = true;
23797
+ const tail2 = this.decoder.decode();
23798
+ if (tail2) this.child.append(this.stream, tail2);
23799
+ }
23800
+ };
23801
+ var nextBridgePid = 1073741824;
23802
+ function installNodeChildProcessBridge(pod, kernel, cred) {
23803
+ const manager = pod.processManager;
23804
+ const originalSpawn = manager.spawn;
23805
+ manager.spawn = (config) => {
23806
+ const resolved = kernel.resolveExecutable(config.command, config.cwd ?? "/", config.env ?? {}, cred);
23807
+ if (resolved?.kind === "builtin" && resolved.command?.name !== "node" && resolved.command?.name !== "nodejs") {
23808
+ return new KernelChildProcess(kernel, cred, config, nextBridgePid++);
23809
+ }
23810
+ return originalSpawn.call(manager, config);
23811
+ };
23812
+ return () => {
23813
+ if (manager.spawn === originalSpawn) return;
23814
+ manager.spawn = originalSpawn;
23815
+ };
23816
+ }
23817
+
23678
23818
  // src/container/container.ts
23679
23819
  var Container = class _Container {
23680
23820
  kernel;
@@ -23685,6 +23825,7 @@ var Container = class _Container {
23685
23825
  hooks;
23686
23826
  disposed = false;
23687
23827
  defaultSession = null;
23828
+ restoreNodeChildProcessBridge;
23688
23829
  constructor(kernel, pod, opts) {
23689
23830
  this.kernel = kernel;
23690
23831
  this.pod = pod;
@@ -23713,6 +23854,7 @@ var Container = class _Container {
23713
23854
  };
23714
23855
  if (opts.timeoutMs !== void 0) this.defaults.timeoutMs = opts.timeoutMs;
23715
23856
  this.hooks = { onStdout: opts.onStdout, onStderr: opts.onStderr };
23857
+ this.restoreNodeChildProcessBridge = installNodeChildProcessBridge(pod, kernel, cred);
23716
23858
  }
23717
23859
  // ── boot ──────────────────────────────────────────────────────────────────
23718
23860
  static async create(opts = {}) {
@@ -24123,6 +24265,7 @@ var Container = class _Container {
24123
24265
  dispose() {
24124
24266
  if (this.disposed) return;
24125
24267
  this.disposed = true;
24268
+ this.restoreNodeChildProcessBridge();
24126
24269
  this.kernel.dispose();
24127
24270
  try {
24128
24271
  this.pod.teardown();