sandboxedjs 0.1.25 → 0.1.27

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 CHANGED
@@ -577,8 +577,8 @@ its kill signal.
577
577
 
578
578
  ## Running in a browser
579
579
 
580
- This package targets Node today, and that is what is tested. If your goal is a browser IDE, here
581
- is exactly where things stand.
580
+ The same `createContainer()` API runs under Node and in modern browsers. Browser execution is
581
+ tested under Vite 8; the remaining browser-specific limits are listed below.
582
582
 
583
583
  **Done — the package no longer hard-depends on Node at import time.** Compression and hashing
584
584
  resolve their implementation at call time (`node:zlib`/`node:crypto` on Node,
@@ -597,7 +597,34 @@ await box.exec("ls -la /"); // shell + coreutils
597
597
  await box.exec("node app/index.js");
598
598
  ```
599
599
 
600
- **Not done three things stand between this and a browser IDE.**
600
+ **Verified in a browser.** Booted under Vite 8, a container starts in the page and the shell,
601
+ coreutils, virtual filesystem and Node runtime all work:
602
+
603
+ ```
604
+ $ uname -a Linux sandbox 5.10.0 (sandboxedjs@sandbox) … x86_64 GNU/Linux
605
+ $ ls -la / the full FHS tree
606
+ $ node -p process.version v22.12.0
607
+ $ cat /etc/os-release SandboxedJS 1.0 (sandbox)
608
+ ```
609
+
610
+ **Vite 8 works through Rolldown's official WASI binding.** Because that binding uses shared
611
+ WebAssembly memory and workers, the page must be cross-origin isolated. For example:
612
+
613
+ ```ts
614
+ // vite.config.ts
615
+ export default {
616
+ server: { headers: {
617
+ "Cross-Origin-Opener-Policy": "same-origin",
618
+ "Cross-Origin-Embedder-Policy": "require-corp",
619
+ } },
620
+ };
621
+ ```
622
+
623
+ Production hosting must return the same two headers. Without them SandboxedJS reports a direct
624
+ configuration error when Vite/Rolldown starts. The compiler is loaded only when an installed
625
+ project actually contains Rolldown, so ordinary container boot does not pay its WASM startup cost.
626
+
627
+ **Not done — these things still stand between this and a complete browser IDE.**
601
628
 
602
629
  - *A service worker.* A preview iframe needs a real URL, and giving it one means a worker on your
603
630
  own origin that intercepts requests and routes them into the container. `request()` works
@@ -607,11 +634,14 @@ await box.exec("node app/index.js");
607
634
  - *Worker isolation.* The runtime executes in whichever realm you boot it from, which in a browser
608
635
  is the main thread — so a long build blocks the UI, and container code can reach page globals.
609
636
  `comlink` is a dependency in anticipation of this and is not used yet.
610
- - *esbuild.* The runtime cannot execute any build of esbuild itself: one dlopens a compiled addon,
637
+ - *esbuild-dependent tools.* The runtime cannot execute any build of esbuild itself: one dlopens a compiled addon,
611
638
  the other drives a Go program through facilities the sandbox does not have. On Node it borrows
612
- the host's `esbuild-wasm`, which is why Vite's dev server works there. In a browser there is
613
- nothing to borrow, so anything routed through esbuild fails until esbuild-wasm runs *inside*
614
- the sandbox.
639
+ the host's `esbuild-wasm`. Vite 8's Rolldown path works in a browser, but tools which call
640
+ esbuild directly still fail until esbuild-wasm runs *inside* the sandbox.
641
+
642
+ Vite prints two warnings about `util` being externalized. They come from `readable-stream`, which
643
+ declares `"util": false` for browsers and falls back on its own; nothing in this package imports
644
+ it.
615
645
 
616
646
  Everything else is already browser-shaped. Nothing in the runtime imports a `node:` builtin except
617
647
  through an explicitly Node-only path that returns `null` elsewhere, compression and hashing pick
@@ -623,7 +653,6 @@ built on `fetch`, `acorn`, `resolve.exports`, `@noble/hashes` and `pako`.
623
653
  - `copyIn()` / `copyOut()` — they read and write the host filesystem, which does not exist.
624
654
  - `expose()` — it opens a real `node:http` listener. Use `request()` to reach an in-container
625
655
  server instead of a host port.
626
- - `python3` — see below.
627
656
  - The `sandboxedjs` CLI, obviously.
628
657
 
629
658
  Those use dynamic imports, so they only fail if you call them.
@@ -736,9 +765,11 @@ Honest list of what does not work:
736
765
  - **Compiled native addons.** A `.node` file cannot be loaded, so a package that ships one has to
737
766
  have a JavaScript or WebAssembly build to fall back on. `rollup` and `esbuild` do, and the
738
767
  runtime redirects those two names to `@rollup/wasm-node` and `esbuild-wasm` automatically when
739
- they are installed. **Vite 8 does not work** for this reason: it builds on Rolldown, whose only
740
- sandbox-viable binding needs WASI and `worker_threads`. Vite 7 runs, dev server included, as do
741
- Express, Koa, Fastify-style apps and plain `http` servers.
768
+ they are installed. Vite 8 is supported through Rolldown's official WASI build (with the browser
769
+ isolation headers above). Express, Koa, Fastify-style apps and plain `http` servers also run.
770
+ - **Concurrent browser Rolldown projects need distinct absolute working directories.** The
771
+ official binding owns one WASI memfs per page; SandboxedJS mirrors each project into it before
772
+ startup. Two live projects using the same path such as `/workspace` can overwrite that mirror.
742
773
  - **`child_process` is asynchronous only.** `spawn`, `exec` and `execFile` run through the kernel,
743
774
  so a child sees the same filesystem and coreutils as the shell. `execSync`, `spawnSync` and
744
775
  `execFileSync` throw `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`: blocking the JavaScript thread on