sandboxedjs 0.1.27 → 0.1.29
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 +52 -7
- package/dist/index.cjs +1540 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +219 -8
- package/dist/index.d.ts +219 -8
- package/dist/index.js +1539 -108
- package/dist/index.js.map +1 -1
- package/dist/worker-entry.js +30822 -0
- package/dist/worker-entry.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -617,11 +617,21 @@ export default {
|
|
|
617
617
|
"Cross-Origin-Opener-Policy": "same-origin",
|
|
618
618
|
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
619
619
|
} },
|
|
620
|
+
// Required as well — see below.
|
|
621
|
+
optimizeDeps: { exclude: ["@rolldown/binding-wasm32-wasi"] },
|
|
620
622
|
};
|
|
621
623
|
```
|
|
622
624
|
|
|
623
625
|
Production hosting must return the same two headers. Without them SandboxedJS reports a direct
|
|
624
|
-
configuration error when Vite/Rolldown starts.
|
|
626
|
+
configuration error when Vite/Rolldown starts.
|
|
627
|
+
|
|
628
|
+
`optimizeDeps.exclude` matters just as much, and fails less obviously. The binding starts its
|
|
629
|
+
WASI worker with `new Worker(new URL("@rolldown/binding-wasm32-wasi/wasi-worker-browser.mjs",
|
|
630
|
+
import.meta.url))`. A bundler that pre-bundles the package rewrites that URL to a path inside its
|
|
631
|
+
own dependency cache, where the worker file does not exist — so the dev server answers with
|
|
632
|
+
`index.html` and the browser rejects it for its MIME type, several layers away from anything that
|
|
633
|
+
mentions Rolldown. Excluding the binding leaves it served from `node_modules`, where that URL
|
|
634
|
+
resolves. The compiler is loaded only when an installed
|
|
625
635
|
project actually contains Rolldown, so ordinary container boot does not pay its WASM startup cost.
|
|
626
636
|
|
|
627
637
|
**Not done — these things still stand between this and a complete browser IDE.**
|
|
@@ -758,6 +768,31 @@ Two caveats worth knowing:
|
|
|
758
768
|
itself reports status correctly and can be relied on in `&&` chains.
|
|
759
769
|
- **No hardware acceleration and no native codecs** beyond what the WebAssembly build ships.
|
|
760
770
|
|
|
771
|
+
## Isolation
|
|
772
|
+
|
|
773
|
+
By default each guest program runs on its own thread, in a Worker. The volume, the kernel, the
|
|
774
|
+
coreutils and the process table stay on the thread that created the container, and the program
|
|
775
|
+
reaches them through a `SharedArrayBuffer` channel it can wait on synchronously.
|
|
776
|
+
|
|
777
|
+
Two things follow from that. Guest code no longer shares your page's realm, so it cannot reach
|
|
778
|
+
your application's globals. And `child_process.execSync`, `spawnSync` and `execFileSync` work —
|
|
779
|
+
they cannot be expressed any other way, because a synchronous call has to block its caller while
|
|
780
|
+
the child it is waiting for still makes progress, which is impossible when both are the same
|
|
781
|
+
thread.
|
|
782
|
+
|
|
783
|
+
It is chosen automatically and falls back on its own, so nothing that runs today stops running:
|
|
784
|
+
|
|
785
|
+
| Condition | What happens |
|
|
786
|
+
|---|---|
|
|
787
|
+
| `SharedArrayBuffer` unavailable, or the page is not cross-origin isolated | Falls back to the in-realm runtime |
|
|
788
|
+
| The guest bundle cannot be loaded (a bundler moved or rewrote it) | Falls back to the in-realm runtime |
|
|
789
|
+
| `modules` supplied by the host | Falls back — live JavaScript objects cannot cross a thread |
|
|
790
|
+
| The project has `rolldown` installed | *That process* runs in-realm; the rest still get a thread |
|
|
791
|
+
|
|
792
|
+
In a browser this needs the same COOP/COEP headers Rolldown does, which is the usual reason to
|
|
793
|
+
find yourself in the fallback. `createContainer({ isolation: "realm" })` opts out entirely, and
|
|
794
|
+
`workerUrl` points at the guest bundle when a bundler has moved it.
|
|
795
|
+
|
|
761
796
|
## Known limits
|
|
762
797
|
|
|
763
798
|
Honest list of what does not work:
|
|
@@ -765,15 +800,25 @@ Honest list of what does not work:
|
|
|
765
800
|
- **Compiled native addons.** A `.node` file cannot be loaded, so a package that ships one has to
|
|
766
801
|
have a JavaScript or WebAssembly build to fall back on. `rollup` and `esbuild` do, and the
|
|
767
802
|
runtime redirects those two names to `@rollup/wasm-node` and `esbuild-wasm` automatically when
|
|
768
|
-
they are installed. Vite 8 is supported through Rolldown's official WASI build
|
|
769
|
-
|
|
803
|
+
they are installed. Vite 8 is supported through Rolldown's official WASI build **in a browser
|
|
804
|
+
host** (with the two configuration steps above). Express, Koa, Fastify-style apps and plain
|
|
805
|
+
`http` servers also run.
|
|
806
|
+
- **Vite 8 / Rolldown does not work when the host is Node.** The binding has two builds. The
|
|
807
|
+
browser one owns a `memfs` volume, which SandboxedJS mirrors the project into; the Node one
|
|
808
|
+
builds a `node:wasi` instance that preopens the *real* filesystem root, and there is no way to
|
|
809
|
+
hand it a different one. Rolldown therefore looks for `/app/my-app/index.html` on your actual
|
|
810
|
+
disk, does not find it, and the dev server answers every request with its fallback page. Vite 7
|
|
811
|
+
works on both hosts and is what the Node acceptance test pins.
|
|
770
812
|
- **Concurrent browser Rolldown projects need distinct absolute working directories.** The
|
|
771
813
|
official binding owns one WASI memfs per page; SandboxedJS mirrors each project into it before
|
|
772
814
|
startup. Two live projects using the same path such as `/workspace` can overwrite that mirror.
|
|
773
|
-
- **`child_process` is
|
|
774
|
-
so a child sees the same filesystem and coreutils as the
|
|
775
|
-
`
|
|
776
|
-
|
|
815
|
+
- **`child_process` is synchronous only under the Worker pod.** `spawn`, `exec` and `execFile`
|
|
816
|
+
always work and run through the kernel, so a child sees the same filesystem and coreutils as the
|
|
817
|
+
shell. `execSync`, `spawnSync` and `execFileSync` need the guest program to be on its own thread
|
|
818
|
+
— see *Isolation* above. Where it is, they work; where it is not, they throw
|
|
819
|
+
`ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` naming the command they were asked to run, and the way
|
|
820
|
+
through is to answer **No** to a prompt like `npm create vite`'s "Install with npm and start
|
|
821
|
+
now?" and run `npm install && npm run dev` from the shell instead.
|
|
777
822
|
- **No `net`, `tls`, `worker_threads` or `vm`.** `http` and `https` are served by a virtual stack
|
|
778
823
|
that `request()` talks to directly, so servers work; raw sockets do not.
|
|
779
824
|
- **Python is CPython via Pyodide.** The standard library is the real one. A C
|