sandboxedjs 0.1.47 → 0.1.48

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.d.cts CHANGED
@@ -993,6 +993,10 @@ declare class MirroringVolume implements RuntimeVolume {
993
993
  readFileSync(path: string): Uint8Array;
994
994
  readdirSync(path: string): string[];
995
995
  lstatSync(path: string): VolumeStat;
996
+ /** The mirror's copy of a file, if it has one and we are allowed to look. */
997
+ private fromMirror;
998
+ /** The mirror's entries for a directory, for merging into a listing. */
999
+ private mirrorNames;
996
1000
  readlinkSync(path: string): string;
997
1001
  getStats(): VolumeStats;
998
1002
  writeFileSync(path: string, data: string | Uint8Array): void;
@@ -1002,7 +1006,35 @@ declare class MirroringVolume implements RuntimeVolume {
1002
1006
  }): void;
1003
1007
  rmdirSync(path: string): void;
1004
1008
  unlinkSync(path: string): void;
1009
+ /**
1010
+ * Rename, carrying anything the mirrored engine put there.
1011
+ *
1012
+ * This is the operation the dependency optimizer is built on, and the one
1013
+ * that used to destroy its output. Vite bundles into a temporary directory
1014
+ * and renames it into place when it is complete — but only half of that
1015
+ * directory is ever on this volume. Vite writes `_metadata.json` and
1016
+ * `package.json` through here; Rolldown writes the actual bundles through
1017
+ * WASI into the mirror. Renaming moved the half that was here and then
1018
+ * `sync(from)` deleted the half that was not, because from this side the
1019
+ * source directory had simply gone.
1020
+ *
1021
+ * What survived was a `deps` directory holding metadata that described five
1022
+ * optimized dependencies and contained none of them — which Vite reports, on
1023
+ * the failed read, as `504 Outdated Optimize Dep`. Nothing in that message is
1024
+ * true, and following it leads to hashes rather than to a missing file.
1025
+ *
1026
+ * So the mirror's side of the move is collected first, and lands here as
1027
+ * part of the rename.
1028
+ */
1005
1029
  renameSync(from: string, to: string): void;
1030
+ /**
1031
+ * Copy whatever the mirror holds under `from` into this volume under `to`.
1032
+ *
1033
+ * Deliberately not filtered the way {@link absorb} is: this walks one
1034
+ * directory that is being renamed, not the whole project, so the subtree is
1035
+ * small and `node_modules` is exactly where the interesting case lives.
1036
+ */
1037
+ private collect;
1006
1038
  symlinkSync(target: string, path: string): void;
1007
1039
  linkSync(existing: string, path: string): void;
1008
1040
  truncateSync(path: string, length?: number): void;
package/dist/index.d.ts CHANGED
@@ -993,6 +993,10 @@ declare class MirroringVolume implements RuntimeVolume {
993
993
  readFileSync(path: string): Uint8Array;
994
994
  readdirSync(path: string): string[];
995
995
  lstatSync(path: string): VolumeStat;
996
+ /** The mirror's copy of a file, if it has one and we are allowed to look. */
997
+ private fromMirror;
998
+ /** The mirror's entries for a directory, for merging into a listing. */
999
+ private mirrorNames;
996
1000
  readlinkSync(path: string): string;
997
1001
  getStats(): VolumeStats;
998
1002
  writeFileSync(path: string, data: string | Uint8Array): void;
@@ -1002,7 +1006,35 @@ declare class MirroringVolume implements RuntimeVolume {
1002
1006
  }): void;
1003
1007
  rmdirSync(path: string): void;
1004
1008
  unlinkSync(path: string): void;
1009
+ /**
1010
+ * Rename, carrying anything the mirrored engine put there.
1011
+ *
1012
+ * This is the operation the dependency optimizer is built on, and the one
1013
+ * that used to destroy its output. Vite bundles into a temporary directory
1014
+ * and renames it into place when it is complete — but only half of that
1015
+ * directory is ever on this volume. Vite writes `_metadata.json` and
1016
+ * `package.json` through here; Rolldown writes the actual bundles through
1017
+ * WASI into the mirror. Renaming moved the half that was here and then
1018
+ * `sync(from)` deleted the half that was not, because from this side the
1019
+ * source directory had simply gone.
1020
+ *
1021
+ * What survived was a `deps` directory holding metadata that described five
1022
+ * optimized dependencies and contained none of them — which Vite reports, on
1023
+ * the failed read, as `504 Outdated Optimize Dep`. Nothing in that message is
1024
+ * true, and following it leads to hashes rather than to a missing file.
1025
+ *
1026
+ * So the mirror's side of the move is collected first, and lands here as
1027
+ * part of the rename.
1028
+ */
1005
1029
  renameSync(from: string, to: string): void;
1030
+ /**
1031
+ * Copy whatever the mirror holds under `from` into this volume under `to`.
1032
+ *
1033
+ * Deliberately not filtered the way {@link absorb} is: this walks one
1034
+ * directory that is being renamed, not the whole project, so the subtree is
1035
+ * small and `node_modules` is exactly where the interesting case lives.
1036
+ */
1037
+ private collect;
1006
1038
  symlinkSync(target: string, path: string): void;
1007
1039
  linkSync(existing: string, path: string): void;
1008
1040
  truncateSync(path: string, length?: number): void;
package/dist/index.js CHANGED
@@ -20565,7 +20565,9 @@ function safeTarget(destination, name) {
20565
20565
  return join(destination, clean2);
20566
20566
  }
20567
20567
  function stripPackageRoot(name) {
20568
- return name.replace(/^\.\//, "").replace(/^package\//, "").replace(/\/$/, "");
20568
+ const clean2 = name.replace(/^\.\//, "").replace(/\/$/, "");
20569
+ const slash = clean2.indexOf("/");
20570
+ return slash === -1 ? "" : clean2.slice(slash + 1);
20569
20571
  }
20570
20572
  function text(bytes2, start2, length) {
20571
20573
  return new TextDecoder().decode(bytes2.subarray(start2, start2 + length)).replace(/\0.*$/, "").trim();
@@ -26611,15 +26613,91 @@ var MirroringVolume = class {
26611
26613
  mirror.writeFileSync(path, this.inner.readFileSync(path));
26612
26614
  });
26613
26615
  }
26614
- // ── reads: straight through ───────────────────────────────────────────────
26616
+ // ── reads: straight through, then the mirror ──────────────────────────────
26617
+ /*
26618
+ * A file the bundler produced exists only in the mirror until something
26619
+ * asks for it here.
26620
+ *
26621
+ * {@link absorb} was the original answer and is not enough on its own. It
26622
+ * runs when a process ends — a dev server never ends — and it skips
26623
+ * `node_modules`, where Vite keeps the one output that a dev server depends
26624
+ * on: `node_modules/.vite/deps`. Between those two, the entire pre-bundled
26625
+ * dependency set stayed invisible to the container that had to serve it.
26626
+ *
26627
+ * The symptom was almost perfectly disguised. Vite writes `_metadata.json`
26628
+ * itself, through this volume, so the directory looked half-populated and
26629
+ * the metadata listed every dependency as optimized. Rolldown wrote the
26630
+ * actual bundles through WASI into the mirror, where nothing brought them
26631
+ * back. Vite then read a file that was not there — and reports a failed read
26632
+ * of an optimized dependency as `504 Outdated Optimize Dep`, which describes
26633
+ * a stale hash and sends everyone looking at hashes. The hash was never
26634
+ * wrong. The file was missing.
26635
+ *
26636
+ * Falling back on read fixes it wherever it happens, for any path, without
26637
+ * polling and without depending on how the engine chose to write.
26638
+ */
26615
26639
  readFileSync(path) {
26616
- return this.inner.readFileSync(path);
26640
+ try {
26641
+ return this.inner.readFileSync(path);
26642
+ } catch (error) {
26643
+ const produced = this.fromMirror(path);
26644
+ if (!produced) throw error;
26645
+ try {
26646
+ this.ensureDirectory(dirname(path));
26647
+ this.inner.writeFileSync(path, produced);
26648
+ } catch {
26649
+ }
26650
+ return produced;
26651
+ }
26617
26652
  }
26618
26653
  readdirSync(path) {
26619
- return this.inner.readdirSync(path);
26654
+ let here = [];
26655
+ let missing;
26656
+ try {
26657
+ here = this.inner.readdirSync(path);
26658
+ } catch (error) {
26659
+ missing = error;
26660
+ }
26661
+ const mirrored = this.mirrorNames(path);
26662
+ if (!mirrored) {
26663
+ if (missing) throw missing;
26664
+ return here;
26665
+ }
26666
+ return [.../* @__PURE__ */ new Set([...here, ...mirrored])].sort();
26620
26667
  }
26621
26668
  lstatSync(path) {
26622
- return this.inner.lstatSync(path);
26669
+ try {
26670
+ return this.inner.lstatSync(path);
26671
+ } catch (error) {
26672
+ if (this.fromMirror(path)) {
26673
+ try {
26674
+ this.readFileSync(path);
26675
+ return this.inner.lstatSync(path);
26676
+ } catch {
26677
+ }
26678
+ }
26679
+ throw error;
26680
+ }
26681
+ }
26682
+ /** The mirror's copy of a file, if it has one and we are allowed to look. */
26683
+ fromMirror(path) {
26684
+ const mirror = this.mirror;
26685
+ if (!mirror?.readFileSync || !mirror.lstatSync || !this.mirrored(path)) return void 0;
26686
+ try {
26687
+ if (!mirror.lstatSync(path).isDirectory()) return mirror.readFileSync(path);
26688
+ } catch {
26689
+ }
26690
+ return void 0;
26691
+ }
26692
+ /** The mirror's entries for a directory, for merging into a listing. */
26693
+ mirrorNames(path) {
26694
+ const mirror = this.mirror;
26695
+ if (!mirror?.readdirSync || !this.mirrored(path)) return void 0;
26696
+ try {
26697
+ return mirror.readdirSync(path);
26698
+ } catch {
26699
+ return void 0;
26700
+ }
26623
26701
  }
26624
26702
  readlinkSync(path) {
26625
26703
  return this.inner.readlinkSync(path);
@@ -26648,11 +26726,76 @@ var MirroringVolume = class {
26648
26726
  this.inner.unlinkSync(path);
26649
26727
  this.sync(path);
26650
26728
  }
26729
+ /**
26730
+ * Rename, carrying anything the mirrored engine put there.
26731
+ *
26732
+ * This is the operation the dependency optimizer is built on, and the one
26733
+ * that used to destroy its output. Vite bundles into a temporary directory
26734
+ * and renames it into place when it is complete — but only half of that
26735
+ * directory is ever on this volume. Vite writes `_metadata.json` and
26736
+ * `package.json` through here; Rolldown writes the actual bundles through
26737
+ * WASI into the mirror. Renaming moved the half that was here and then
26738
+ * `sync(from)` deleted the half that was not, because from this side the
26739
+ * source directory had simply gone.
26740
+ *
26741
+ * What survived was a `deps` directory holding metadata that described five
26742
+ * optimized dependencies and contained none of them — which Vite reports, on
26743
+ * the failed read, as `504 Outdated Optimize Dep`. Nothing in that message is
26744
+ * true, and following it leads to hashes rather than to a missing file.
26745
+ *
26746
+ * So the mirror's side of the move is collected first, and lands here as
26747
+ * part of the rename.
26748
+ */
26651
26749
  renameSync(from, to) {
26652
26750
  this.inner.renameSync(from, to);
26751
+ this.collect(from, to);
26653
26752
  this.sync(from);
26654
26753
  this.sync(to);
26655
26754
  }
26755
+ /**
26756
+ * Copy whatever the mirror holds under `from` into this volume under `to`.
26757
+ *
26758
+ * Deliberately not filtered the way {@link absorb} is: this walks one
26759
+ * directory that is being renamed, not the whole project, so the subtree is
26760
+ * small and `node_modules` is exactly where the interesting case lives.
26761
+ */
26762
+ collect(from, to) {
26763
+ const mirror = this.mirror;
26764
+ if (!mirror?.readdirSync || !mirror.readFileSync || !mirror.lstatSync) return;
26765
+ if (!this.mirrored(from)) return;
26766
+ const walk = (source, destination) => {
26767
+ let stat2;
26768
+ try {
26769
+ stat2 = mirror.lstatSync(source);
26770
+ } catch {
26771
+ return;
26772
+ }
26773
+ if (stat2.isSymbolicLink()) return;
26774
+ if (stat2.isDirectory()) {
26775
+ let names;
26776
+ try {
26777
+ names = mirror.readdirSync(source);
26778
+ } catch {
26779
+ return;
26780
+ }
26781
+ this.ensureDirectory(destination);
26782
+ for (const name of names) walk(join(source, name), join(destination, name));
26783
+ return;
26784
+ }
26785
+ try {
26786
+ this.inner.lstatSync(destination);
26787
+ return;
26788
+ } catch {
26789
+ }
26790
+ try {
26791
+ const bytes2 = mirror.readFileSync(source);
26792
+ this.ensureDirectory(dirname(destination));
26793
+ this.inner.writeFileSync(destination, bytes2);
26794
+ } catch {
26795
+ }
26796
+ };
26797
+ this.safely(() => walk(from, to));
26798
+ }
26656
26799
  symlinkSync(target, path) {
26657
26800
  this.inner.symlinkSync(target, path);
26658
26801
  this.sync(path);