sandboxedjs 0.1.97 → 0.1.99

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
@@ -4273,7 +4273,8 @@ function md5Hex(input) {
4273
4273
  var isNode, zlibPromise, cryptoPromise, SUBTLE_NAMES, UnsupportedAlgorithmError;
4274
4274
  var init_binary = __esm({
4275
4275
  "src/util/binary.ts"() {
4276
- isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
4276
+ isNode = typeof window === "undefined" && typeof document === "undefined" && typeof process !== "undefined" && process.versions != null && process.versions.node != null && /* A shim has no `release.name`, and Node's has said "node" since v3. */
4277
+ process.release?.name === "node";
4277
4278
  zlibPromise = null;
4278
4279
  cryptoPromise = null;
4279
4280
  SUBTLE_NAMES = {
@@ -20958,7 +20959,7 @@ var wheels_default = {
20958
20959
 
20959
20960
  // package.json
20960
20961
  var package_default = {
20961
- version: "0.1.97"};
20962
+ version: "0.1.99"};
20962
20963
 
20963
20964
  // src/python/extension-abi.ts
20964
20965
  var EXTENSION_ABI = {
@@ -38658,6 +38659,22 @@ var WS_DATA = "sandboxedjs:ws-data";
38658
38659
  var WS_CLOSE = "sandboxedjs:ws-close";
38659
38660
  var WS_ERROR = "sandboxedjs:ws-error";
38660
38661
 
38662
+ // src/preview/router.ts
38663
+ var LOOPBACK_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[?::1\]?)$/i;
38664
+ function containerTarget(value) {
38665
+ let url;
38666
+ try {
38667
+ url = new URL(value.trim());
38668
+ } catch {
38669
+ return null;
38670
+ }
38671
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
38672
+ if (!LOOPBACK_HOST.test(url.hostname)) return null;
38673
+ const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
38674
+ if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
38675
+ return { port, path: `${url.pathname}${url.search}` };
38676
+ }
38677
+
38661
38678
  // src/preview/register.ts
38662
38679
  function serveContainerOn(port, box) {
38663
38680
  port.onmessage = async (event) => {
@@ -38692,20 +38709,6 @@ function serveContainerOn(port, box) {
38692
38709
  };
38693
38710
  port.start?.();
38694
38711
  }
38695
- var LOOPBACK_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[?::1\]?)$/i;
38696
- function containerTarget(value) {
38697
- let url;
38698
- try {
38699
- url = new URL(value.trim());
38700
- } catch {
38701
- return null;
38702
- }
38703
- if (url.protocol !== "http:" && url.protocol !== "https:") return null;
38704
- if (!LOOPBACK_HOST.test(url.hostname)) return null;
38705
- const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
38706
- if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
38707
- return { port, path: `${url.pathname}${url.search}` };
38708
- }
38709
38712
  async function createPreview(box, options = {}) {
38710
38713
  if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) return null;
38711
38714
  const scriptUrl = options.scriptUrl ?? new URL("./service-worker.js?no-inline", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
package/dist/index.d.cts CHANGED
@@ -1590,19 +1590,22 @@ declare function startRuntimeWorker(options?: {
1590
1590
  declare function syncChannelSupported(): boolean;
1591
1591
 
1592
1592
  /**
1593
- * Wiring a container's HTTP servers up to real URLs in the page.
1593
+ * The routing a preview service worker does, separated from the worker itself.
1594
1594
  *
1595
- * The service worker does the routing; this is the half that lives in the page
1596
- * and actually knows about the container.
1595
+ * A service worker is awkward to test it needs a browser, a registration and
1596
+ * a secure context — but almost none of what makes this correct is about being
1597
+ * a service worker. The interesting part is the bookkeeping: which client is
1598
+ * previewing which port, which requests belong to a preview at all, and how a
1599
+ * response is rebuilt on the way back. That lives here, where it can be
1600
+ * exercised directly.
1597
1601
  *
1598
- * **Read the origin note before using this.** A preview served this way runs on
1599
- * *your* origin, so scripts inside it can reach `window.parent`, your cookies
1600
- * and your `localStorage` the sandbox contains the program's *filesystem and
1601
- * process table*, not the page it serves. For code you did not write, either
1602
- * host the preview on a separate origin, or use {@link renderInto}, which puts
1603
- * the response in an iframe with no origin at all.
1602
+ * The rule this implements, and the reason it exists: requests are routed by
1603
+ * **who is asking**, not by what the path looks like. An iframe navigates once
1604
+ * to `/__sbx__/<port>/`; every later request from that client however
1605
+ * absolute its path is recognised by its client id. Nothing has to rewrite
1606
+ * `/src/main.js` or `/@vite/client`, which is what makes a real dev server
1607
+ * work rather than only a single page.
1604
1608
  */
1605
-
1606
1609
  /** A container-local server, named by port rather than by an address. */
1607
1610
  interface ContainerTarget {
1608
1611
  port: number;
@@ -1618,10 +1621,31 @@ interface ContainerTarget {
1618
1621
  * is listening, so a frame pointed at it fails with "refused to connect"
1619
1622
  * rather than failing visibly as a routing mistake.
1620
1623
  *
1621
- * Exported separately from {@link Preview.resolve} because it is pure, and a
1622
- * translation table is worth testing without a service worker in the way.
1624
+ * The same translation serves two callers. A host reading an address out of a
1625
+ * build log needs it to point a frame somewhere (`Preview.resolve`), and the
1626
+ * service worker needs it for the other direction: a page *inside* a preview
1627
+ * asking its own backend for `http://localhost:8000/api` means the container's
1628
+ * port 8000, not the reader's machine.
1629
+ *
1630
+ * Kept pure, and kept here rather than beside the host half, because the
1631
+ * worker bundles this module and not that one.
1623
1632
  */
1624
1633
  declare function containerTarget(value: string): ContainerTarget | null;
1634
+
1635
+ /**
1636
+ * Wiring a container's HTTP servers up to real URLs in the page.
1637
+ *
1638
+ * The service worker does the routing; this is the half that lives in the page
1639
+ * and actually knows about the container.
1640
+ *
1641
+ * **Read the origin note before using this.** A preview served this way runs on
1642
+ * *your* origin, so scripts inside it can reach `window.parent`, your cookies
1643
+ * and your `localStorage` — the sandbox contains the program's *filesystem and
1644
+ * process table*, not the page it serves. For code you did not write, either
1645
+ * host the preview on a separate origin, or use {@link renderInto}, which puts
1646
+ * the response in an iframe with no origin at all.
1647
+ */
1648
+
1625
1649
  interface PreviewOptions {
1626
1650
  /** Where the worker script lives; defaults to the copy shipped beside the bundle. */
1627
1651
  scriptUrl?: string | URL;
package/dist/index.d.ts CHANGED
@@ -1590,19 +1590,22 @@ declare function startRuntimeWorker(options?: {
1590
1590
  declare function syncChannelSupported(): boolean;
1591
1591
 
1592
1592
  /**
1593
- * Wiring a container's HTTP servers up to real URLs in the page.
1593
+ * The routing a preview service worker does, separated from the worker itself.
1594
1594
  *
1595
- * The service worker does the routing; this is the half that lives in the page
1596
- * and actually knows about the container.
1595
+ * A service worker is awkward to test it needs a browser, a registration and
1596
+ * a secure context — but almost none of what makes this correct is about being
1597
+ * a service worker. The interesting part is the bookkeeping: which client is
1598
+ * previewing which port, which requests belong to a preview at all, and how a
1599
+ * response is rebuilt on the way back. That lives here, where it can be
1600
+ * exercised directly.
1597
1601
  *
1598
- * **Read the origin note before using this.** A preview served this way runs on
1599
- * *your* origin, so scripts inside it can reach `window.parent`, your cookies
1600
- * and your `localStorage` the sandbox contains the program's *filesystem and
1601
- * process table*, not the page it serves. For code you did not write, either
1602
- * host the preview on a separate origin, or use {@link renderInto}, which puts
1603
- * the response in an iframe with no origin at all.
1602
+ * The rule this implements, and the reason it exists: requests are routed by
1603
+ * **who is asking**, not by what the path looks like. An iframe navigates once
1604
+ * to `/__sbx__/<port>/`; every later request from that client however
1605
+ * absolute its path is recognised by its client id. Nothing has to rewrite
1606
+ * `/src/main.js` or `/@vite/client`, which is what makes a real dev server
1607
+ * work rather than only a single page.
1604
1608
  */
1605
-
1606
1609
  /** A container-local server, named by port rather than by an address. */
1607
1610
  interface ContainerTarget {
1608
1611
  port: number;
@@ -1618,10 +1621,31 @@ interface ContainerTarget {
1618
1621
  * is listening, so a frame pointed at it fails with "refused to connect"
1619
1622
  * rather than failing visibly as a routing mistake.
1620
1623
  *
1621
- * Exported separately from {@link Preview.resolve} because it is pure, and a
1622
- * translation table is worth testing without a service worker in the way.
1624
+ * The same translation serves two callers. A host reading an address out of a
1625
+ * build log needs it to point a frame somewhere (`Preview.resolve`), and the
1626
+ * service worker needs it for the other direction: a page *inside* a preview
1627
+ * asking its own backend for `http://localhost:8000/api` means the container's
1628
+ * port 8000, not the reader's machine.
1629
+ *
1630
+ * Kept pure, and kept here rather than beside the host half, because the
1631
+ * worker bundles this module and not that one.
1623
1632
  */
1624
1633
  declare function containerTarget(value: string): ContainerTarget | null;
1634
+
1635
+ /**
1636
+ * Wiring a container's HTTP servers up to real URLs in the page.
1637
+ *
1638
+ * The service worker does the routing; this is the half that lives in the page
1639
+ * and actually knows about the container.
1640
+ *
1641
+ * **Read the origin note before using this.** A preview served this way runs on
1642
+ * *your* origin, so scripts inside it can reach `window.parent`, your cookies
1643
+ * and your `localStorage` — the sandbox contains the program's *filesystem and
1644
+ * process table*, not the page it serves. For code you did not write, either
1645
+ * host the preview on a separate origin, or use {@link renderInto}, which puts
1646
+ * the response in an iframe with no origin at all.
1647
+ */
1648
+
1625
1649
  interface PreviewOptions {
1626
1650
  /** Where the worker script lives; defaults to the copy shipped beside the bundle. */
1627
1651
  scriptUrl?: string | URL;
package/dist/index.js CHANGED
@@ -4256,7 +4256,8 @@ function md5Hex(input) {
4256
4256
  var isNode, zlibPromise, cryptoPromise, SUBTLE_NAMES, UnsupportedAlgorithmError;
4257
4257
  var init_binary = __esm({
4258
4258
  "src/util/binary.ts"() {
4259
- isNode = typeof process !== "undefined" && process.versions != null && process.versions.node != null;
4259
+ isNode = typeof window === "undefined" && typeof document === "undefined" && typeof process !== "undefined" && process.versions != null && process.versions.node != null && /* A shim has no `release.name`, and Node's has said "node" since v3. */
4260
+ process.release?.name === "node";
4260
4261
  zlibPromise = null;
4261
4262
  cryptoPromise = null;
4262
4263
  SUBTLE_NAMES = {
@@ -20941,7 +20942,7 @@ var wheels_default = {
20941
20942
 
20942
20943
  // package.json
20943
20944
  var package_default = {
20944
- version: "0.1.97"};
20945
+ version: "0.1.99"};
20945
20946
 
20946
20947
  // src/python/extension-abi.ts
20947
20948
  var EXTENSION_ABI = {
@@ -38641,6 +38642,22 @@ var WS_DATA = "sandboxedjs:ws-data";
38641
38642
  var WS_CLOSE = "sandboxedjs:ws-close";
38642
38643
  var WS_ERROR = "sandboxedjs:ws-error";
38643
38644
 
38645
+ // src/preview/router.ts
38646
+ var LOOPBACK_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[?::1\]?)$/i;
38647
+ function containerTarget(value) {
38648
+ let url;
38649
+ try {
38650
+ url = new URL(value.trim());
38651
+ } catch {
38652
+ return null;
38653
+ }
38654
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
38655
+ if (!LOOPBACK_HOST.test(url.hostname)) return null;
38656
+ const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
38657
+ if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
38658
+ return { port, path: `${url.pathname}${url.search}` };
38659
+ }
38660
+
38644
38661
  // src/preview/register.ts
38645
38662
  function serveContainerOn(port, box) {
38646
38663
  port.onmessage = async (event) => {
@@ -38675,20 +38692,6 @@ function serveContainerOn(port, box) {
38675
38692
  };
38676
38693
  port.start?.();
38677
38694
  }
38678
- var LOOPBACK_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[?::1\]?)$/i;
38679
- function containerTarget(value) {
38680
- let url;
38681
- try {
38682
- url = new URL(value.trim());
38683
- } catch {
38684
- return null;
38685
- }
38686
- if (url.protocol !== "http:" && url.protocol !== "https:") return null;
38687
- if (!LOOPBACK_HOST.test(url.hostname)) return null;
38688
- const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
38689
- if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
38690
- return { port, path: `${url.pathname}${url.search}` };
38691
- }
38692
38695
  async function createPreview(box, options = {}) {
38693
38696
  if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) return null;
38694
38697
  const scriptUrl = options.scriptUrl ?? new URL("./service-worker.js?no-inline", import.meta.url);
@@ -772,7 +772,8 @@ function createSbxFs(FS, client, errnoCodes) {
772
772
  }
773
773
 
774
774
  // src/util/binary.ts
775
- typeof process !== "undefined" && process.versions != null && process.versions.node != null;
775
+ typeof window === "undefined" && typeof document === "undefined" && typeof process !== "undefined" && process.versions != null && process.versions.node != null && /* A shim has no `release.name`, and Node's has said "node" since v3. */
776
+ process.release?.name === "node";
776
777
  async function nodeBuiltin(name) {
777
778
  const specifier = `node:${name}`;
778
779
  return await import(
@@ -349,6 +349,20 @@ function previewSocketSource() {
349
349
 
350
350
  // src/preview/router.ts
351
351
  var CLAIM = /(?:^|\/)__sbx__\/(\d+)(?:\/|$)/;
352
+ var LOOPBACK_HOST = /^(?:localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[?::1\]?)$/i;
353
+ function containerTarget(value) {
354
+ let url;
355
+ try {
356
+ url = new URL(value.trim());
357
+ } catch {
358
+ return null;
359
+ }
360
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
361
+ if (!LOOPBACK_HOST.test(url.hostname)) return null;
362
+ const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
363
+ if (!Number.isInteger(port) || port < 1 || port > 65535) return null;
364
+ return { port, path: `${url.pathname}${url.search}` };
365
+ }
352
366
  var OUTDATED = /outdated optimize dep/i;
353
367
  var NOT_CONNECTED = 503;
354
368
  var PreviewRouter = class {
@@ -549,7 +563,13 @@ worker.addEventListener("message", (event) => {
549
563
  });
550
564
  worker.addEventListener("fetch", (event) => {
551
565
  const url = new URL(event.request.url);
552
- if (url.origin !== worker.location.origin) return;
566
+ if (url.origin !== worker.location.origin) {
567
+ const port2 = router.portFor(event.clientId);
568
+ const target = port2 === void 0 ? null : containerTarget(url.href);
569
+ if (!target) return;
570
+ event.respondWith(router.fetch(target.port, target.path, event.request, event.clientId));
571
+ return;
572
+ }
553
573
  const claimed = router.claimedPort(url.pathname);
554
574
  if (claimed !== null && event.request.mode === "navigate") {
555
575
  router.bind(event.resultingClientId || event.clientId, claimed);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxedjs",
3
- "version": "0.1.97",
3
+ "version": "0.1.99",
4
4
  "description": "A Linux-like container that runs entirely inside Node.js — POSIX shell, ~140 coreutils, Node.js and Python runtimes, virtual filesystem and networking. No Docker, no VM, no native modules.",
5
5
  "type": "module",
6
6
  "license": "MIT",