@volter/tabnode 0.5.44 → 0.5.46

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.
@@ -8686,6 +8686,26 @@ function createFsBindings(Bytes = () => Buffer$9) {
8686
8686
  if (position === null || position === void 0 || position < 0) file.position = end + slice.length;
8687
8687
  return slice.length;
8688
8688
  }
8689
+ if (typeof tree2.writeAtSync === "function") {
8690
+ const at22 = position === null || position === void 0 || position < 0 ? file.position : position;
8691
+ tree2.writeAtSync(file.path, slice, at22);
8692
+ if (file.cached !== void 0 && slice.length > 0) {
8693
+ const cached = file.cached;
8694
+ const length2 = Math.max(cached.length, at22 + slice.length);
8695
+ let room = file.room;
8696
+ if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length2) {
8697
+ room = new Uint8Array(Math.max(length2, cached.length * 2, 4096));
8698
+ room.set(cached, 0);
8699
+ } else if (at22 > cached.length) {
8700
+ room.fill(0, cached.length, at22);
8701
+ }
8702
+ room.set(slice, at22);
8703
+ file.cached = room.subarray(0, length2);
8704
+ file.room = room;
8705
+ }
8706
+ if (position === null || position === void 0 || position < 0) file.position = at22 + slice.length;
8707
+ return slice.length;
8708
+ }
8689
8709
  const existing = file.cached ?? (tree2.existsSync(file.path) ? tree2.readFileSync(file.path) : new Uint8Array(0));
8690
8710
  const at3 = (file.flags & flagBits().append) !== 0 ? existing.length : position === null || position === void 0 || position < 0 ? file.position : position;
8691
8711
  const size = Math.max(existing.length, at3 + slice.length);
@@ -31445,6 +31465,8 @@ class VirtualFS {
31445
31465
  if (existed && existing.type === "file") {
31446
31466
  existing.content = content;
31447
31467
  existing.mtime = Date.now();
31468
+ existing.room = void 0;
31469
+ existing.lent = true;
31448
31470
  } else {
31449
31471
  parent.children.set(basename, {
31450
31472
  type: "file",
@@ -31730,6 +31752,7 @@ class VirtualFS {
31730
31752
  if (encoding === "utf8" || encoding === "utf-8") {
31731
31753
  return this.decoder.decode(content);
31732
31754
  }
31755
+ node.lent = true;
31733
31756
  return content;
31734
31757
  }
31735
31758
  /**
@@ -31779,6 +31802,55 @@ class VirtualFS {
31779
31802
  this.notifyWatchers(normalized, "change");
31780
31803
  if ((_a3 = this.eventListeners.get("change")) == null ? void 0 : _a3.size) this.emit("change", normalized, this.decoder.decode(node.content));
31781
31804
  }
31805
+ /**
31806
+ * Bytes written into a file at `position`, as a disk takes them: a gap past
31807
+ * the end reads as zeros, and the file grows in its own buffer as an append
31808
+ * grows it. A database rewrites its log and its pages a page at a time;
31809
+ * writing the whole file again for each page copied Postgres's 16 MB
31810
+ * write-ahead log at every commit. A tree that keeps its files elsewhere
31811
+ * (its own writeFileSync) is written through its own read and write unless
31812
+ * it answers this itself.
31813
+ */
31814
+ writeAtSync(path2, data2, position) {
31815
+ var _a3;
31816
+ if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
31817
+ const existing = this.existsSync(path2) ? this.readFileSync(path2) : new Uint8Array(0);
31818
+ if (data2.byteLength === 0 && this.existsSync(path2)) return;
31819
+ const whole = new Uint8Array(Math.max(existing.byteLength, position + data2.byteLength));
31820
+ whole.set(existing, 0);
31821
+ whole.set(data2, position);
31822
+ this.writeFileSync(path2, whole);
31823
+ return;
31824
+ }
31825
+ const normalized = this.normalizePath(path2);
31826
+ const node = this.getNode(normalized);
31827
+ if (!node) {
31828
+ const whole = new Uint8Array(position + data2.byteLength);
31829
+ whole.set(data2, position);
31830
+ this.writeFileSyncInternal(normalized, whole, true);
31831
+ return;
31832
+ }
31833
+ if (node.type !== "file") throw createNodeError("EISDIR", "open", path2);
31834
+ this.assertWritable(normalized, "open");
31835
+ if (data2.byteLength === 0) return;
31836
+ const current3 = node.content ?? new Uint8Array(0);
31837
+ const length = Math.max(current3.byteLength, position + data2.byteLength);
31838
+ const held = node;
31839
+ let room = held.room;
31840
+ if (!room || held.lent || current3.buffer !== room.buffer || current3.byteOffset !== 0 || room.byteLength < length) {
31841
+ room = new Uint8Array(Math.max(length, current3.byteLength * 2, 4096));
31842
+ room.set(current3, 0);
31843
+ held.lent = false;
31844
+ } else if (position > current3.byteLength) {
31845
+ room.fill(0, current3.byteLength, position);
31846
+ }
31847
+ room.set(data2, position);
31848
+ node.content = room.subarray(0, length);
31849
+ node.room = room;
31850
+ node.mtime = Date.now();
31851
+ this.notifyWatchers(normalized, "change");
31852
+ if ((_a3 = this.eventListeners.get("change")) == null ? void 0 : _a3.size) this.emit("change", normalized, this.decoder.decode(node.content));
31853
+ }
31782
31854
  /**
31783
31855
  * Create directory, optionally with recursive parent creation
31784
31856
  */
@@ -79994,10 +80066,28 @@ function createRequire(vfs2, fsShim, process2, currentDir, moduleCache, options,
79994
80066
  }
79995
80067
  return loadModule(resolved).exports;
79996
80068
  };
79997
- require2.resolve = (id2) => {
80069
+ require2.resolve = (id2, options2) => {
79998
80070
  if (id2 === "fs" || id2 === "process" || id2.startsWith("node:") || builtinModules$1.includes(id2)) {
79999
80071
  return id2;
80000
80072
  }
80073
+ if (options2 && options2.paths !== void 0) {
80074
+ if (!Array.isArray(options2.paths)) {
80075
+ throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options2.paths)}`), { code: "ERR_INVALID_ARG_VALUE" });
80076
+ }
80077
+ options2.paths.forEach((from, index2) => {
80078
+ if (typeof from !== "string") throw Object.assign(new TypeError(`The "paths[${index2}]" argument must be of type string. Received ${typeof from}`), { code: "ERR_INVALID_ARG_TYPE" });
80079
+ });
80080
+ const requireStack = parentModule && typeof parentModule.filename === "string" ? [parentModule.filename] : [];
80081
+ for (const from of options2.paths) {
80082
+ try {
80083
+ return resolveModule(id2, resolve(process2.cwd(), from));
80084
+ } catch {
80085
+ }
80086
+ }
80087
+ throw Object.assign(new Error(`Cannot find module '${id2}'${requireStack.length ? `
80088
+ Require stack:
80089
+ - ${requireStack.join("\n- ")}` : ""}`), { code: "MODULE_NOT_FOUND", requireStack });
80090
+ }
80001
80091
  return resolveModule(id2, currentDir);
80002
80092
  };
80003
80093
  require2.cache = moduleCache;
package/dist/index.mjs CHANGED
@@ -8814,6 +8814,26 @@ function createFsBindings(Bytes = () => Buffer$9) {
8814
8814
  if (position === null || position === void 0 || position < 0) file.position = end + slice.length;
8815
8815
  return slice.length;
8816
8816
  }
8817
+ if (typeof tree2.writeAtSync === "function") {
8818
+ const at22 = position === null || position === void 0 || position < 0 ? file.position : position;
8819
+ tree2.writeAtSync(file.path, slice, at22);
8820
+ if (file.cached !== void 0 && slice.length > 0) {
8821
+ const cached = file.cached;
8822
+ const length2 = Math.max(cached.length, at22 + slice.length);
8823
+ let room = file.room;
8824
+ if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length2) {
8825
+ room = new Uint8Array(Math.max(length2, cached.length * 2, 4096));
8826
+ room.set(cached, 0);
8827
+ } else if (at22 > cached.length) {
8828
+ room.fill(0, cached.length, at22);
8829
+ }
8830
+ room.set(slice, at22);
8831
+ file.cached = room.subarray(0, length2);
8832
+ file.room = room;
8833
+ }
8834
+ if (position === null || position === void 0 || position < 0) file.position = at22 + slice.length;
8835
+ return slice.length;
8836
+ }
8817
8837
  const existing = file.cached ?? (tree2.existsSync(file.path) ? tree2.readFileSync(file.path) : new Uint8Array(0));
8818
8838
  const at2 = (file.flags & flagBits().append) !== 0 ? existing.length : position === null || position === void 0 || position < 0 ? file.position : position;
8819
8839
  const size = Math.max(existing.length, at2 + slice.length);
@@ -31599,6 +31619,8 @@ class VirtualFS {
31599
31619
  if (existed && existing.type === "file") {
31600
31620
  existing.content = content;
31601
31621
  existing.mtime = Date.now();
31622
+ existing.room = void 0;
31623
+ existing.lent = true;
31602
31624
  } else {
31603
31625
  parent.children.set(basename2, {
31604
31626
  type: "file",
@@ -31884,6 +31906,7 @@ class VirtualFS {
31884
31906
  if (encoding === "utf8" || encoding === "utf-8") {
31885
31907
  return this.decoder.decode(content);
31886
31908
  }
31909
+ node.lent = true;
31887
31910
  return content;
31888
31911
  }
31889
31912
  /**
@@ -31933,6 +31956,55 @@ class VirtualFS {
31933
31956
  this.notifyWatchers(normalized, "change");
31934
31957
  if ((_a2 = this.eventListeners.get("change")) == null ? void 0 : _a2.size) this.emit("change", normalized, this.decoder.decode(node.content));
31935
31958
  }
31959
+ /**
31960
+ * Bytes written into a file at `position`, as a disk takes them: a gap past
31961
+ * the end reads as zeros, and the file grows in its own buffer as an append
31962
+ * grows it. A database rewrites its log and its pages a page at a time;
31963
+ * writing the whole file again for each page copied Postgres's 16 MB
31964
+ * write-ahead log at every commit. A tree that keeps its files elsewhere
31965
+ * (its own writeFileSync) is written through its own read and write unless
31966
+ * it answers this itself.
31967
+ */
31968
+ writeAtSync(path2, data2, position) {
31969
+ var _a2;
31970
+ if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
31971
+ const existing = this.existsSync(path2) ? this.readFileSync(path2) : new Uint8Array(0);
31972
+ if (data2.byteLength === 0 && this.existsSync(path2)) return;
31973
+ const whole = new Uint8Array(Math.max(existing.byteLength, position + data2.byteLength));
31974
+ whole.set(existing, 0);
31975
+ whole.set(data2, position);
31976
+ this.writeFileSync(path2, whole);
31977
+ return;
31978
+ }
31979
+ const normalized = this.normalizePath(path2);
31980
+ const node = this.getNode(normalized);
31981
+ if (!node) {
31982
+ const whole = new Uint8Array(position + data2.byteLength);
31983
+ whole.set(data2, position);
31984
+ this.writeFileSyncInternal(normalized, whole, true);
31985
+ return;
31986
+ }
31987
+ if (node.type !== "file") throw createNodeError("EISDIR", "open", path2);
31988
+ this.assertWritable(normalized, "open");
31989
+ if (data2.byteLength === 0) return;
31990
+ const current3 = node.content ?? new Uint8Array(0);
31991
+ const length = Math.max(current3.byteLength, position + data2.byteLength);
31992
+ const held = node;
31993
+ let room = held.room;
31994
+ if (!room || held.lent || current3.buffer !== room.buffer || current3.byteOffset !== 0 || room.byteLength < length) {
31995
+ room = new Uint8Array(Math.max(length, current3.byteLength * 2, 4096));
31996
+ room.set(current3, 0);
31997
+ held.lent = false;
31998
+ } else if (position > current3.byteLength) {
31999
+ room.fill(0, current3.byteLength, position);
32000
+ }
32001
+ room.set(data2, position);
32002
+ node.content = room.subarray(0, length);
32003
+ node.room = room;
32004
+ node.mtime = Date.now();
32005
+ this.notifyWatchers(normalized, "change");
32006
+ if ((_a2 = this.eventListeners.get("change")) == null ? void 0 : _a2.size) this.emit("change", normalized, this.decoder.decode(node.content));
32007
+ }
31936
32008
  /**
31937
32009
  * Create directory, optionally with recursive parent creation
31938
32010
  */
@@ -39655,10 +39727,28 @@ function createRequire(vfs2, fsShim, process2, currentDir, moduleCache, options,
39655
39727
  }
39656
39728
  return loadModule(resolved).exports;
39657
39729
  };
39658
- require2.resolve = (id) => {
39730
+ require2.resolve = (id, options2) => {
39659
39731
  if (id === "fs" || id === "process" || id.startsWith("node:") || builtinModules$1.includes(id)) {
39660
39732
  return id;
39661
39733
  }
39734
+ if (options2 && options2.paths !== void 0) {
39735
+ if (!Array.isArray(options2.paths)) {
39736
+ throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options2.paths)}`), { code: "ERR_INVALID_ARG_VALUE" });
39737
+ }
39738
+ options2.paths.forEach((from, index2) => {
39739
+ if (typeof from !== "string") throw Object.assign(new TypeError(`The "paths[${index2}]" argument must be of type string. Received ${typeof from}`), { code: "ERR_INVALID_ARG_TYPE" });
39740
+ });
39741
+ const requireStack = parentModule && typeof parentModule.filename === "string" ? [parentModule.filename] : [];
39742
+ for (const from of options2.paths) {
39743
+ try {
39744
+ return resolveModule(id, resolve(process2.cwd(), from));
39745
+ } catch {
39746
+ }
39747
+ }
39748
+ throw Object.assign(new Error(`Cannot find module '${id}'${requireStack.length ? `
39749
+ Require stack:
39750
+ - ${requireStack.join("\n- ")}` : ""}`), { code: "MODULE_NOT_FOUND", requireStack });
39751
+ }
39662
39752
  return resolveModule(id, currentDir);
39663
39753
  };
39664
39754
  require2.cache = moduleCache;
@@ -40338,7 +40428,7 @@ class WorkerRuntime {
40338
40428
  this.worker = new Worker(
40339
40429
  new URL(
40340
40430
  /* @vite-ignore */
40341
- "/assets/runtime-worker-CSaX_wiK.js",
40431
+ "/assets/runtime-worker-DuSugZ3P.js",
40342
40432
  import.meta.url
40343
40433
  ),
40344
40434
  { type: "module" }
@@ -204,6 +204,16 @@ export declare class VirtualFS {
204
204
  * read and write unless it answers appends itself.
205
205
  */
206
206
  appendFileSync(path: string, data: string | Uint8Array): void;
207
+ /**
208
+ * Bytes written into a file at `position`, as a disk takes them: a gap past
209
+ * the end reads as zeros, and the file grows in its own buffer as an append
210
+ * grows it. A database rewrites its log and its pages a page at a time;
211
+ * writing the whole file again for each page copied Postgres's 16 MB
212
+ * write-ahead log at every commit. A tree that keeps its files elsewhere
213
+ * (its own writeFileSync) is written through its own read and write unless
214
+ * it answers this itself.
215
+ */
216
+ writeAtSync(path: string, data: Uint8Array, position: number): void;
207
217
  /**
208
218
  * Create directory, optionally with recursive parent creation
209
219
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/tabnode",
3
- "version": "0.5.44",
3
+ "version": "0.5.46",
4
4
  "description": "Node's own library, in a browser tab.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -630,6 +630,30 @@ const fsBinding = {
630
630
  if (position === null || position === undefined || position < 0) file.position = end + slice.length;
631
631
  return slice.length;
632
632
  }
633
+ // A write elsewhere in the file goes where it lands, when the tree takes one: a database's page or log
634
+ // record costs its own bytes, not the file's (Postgres's commits wrote its whole 16 MB log again).
635
+ if (typeof (tree as { writeAtSync?: unknown }).writeAtSync === 'function') {
636
+ const at = position === null || position === undefined || position < 0 ? file.position : position;
637
+ (tree as { writeAtSync(path: string, data: Uint8Array, position: number): void }).writeAtSync(file.path, slice, at);
638
+ // This descriptor's copy takes the same bytes, in a buffer of its own with room, as an append's does: a
639
+ // read after the write is answered from it rather than by reading the whole file again.
640
+ if (file.cached !== undefined && slice.length > 0) {
641
+ const cached = file.cached;
642
+ const length = Math.max(cached.length, at + slice.length);
643
+ let room = file.room;
644
+ if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length) {
645
+ room = new Uint8Array(Math.max(length, cached.length * 2, 4096));
646
+ room.set(cached, 0);
647
+ } else if (at > cached.length) {
648
+ room.fill(0, cached.length, at);
649
+ }
650
+ room.set(slice, at);
651
+ file.cached = room.subarray(0, length);
652
+ file.room = room;
653
+ }
654
+ if (position === null || position === undefined || position < 0) file.position = at + slice.length;
655
+ return slice.length;
656
+ }
633
657
  const existing = file.cached ?? (tree.existsSync(file.path) ? tree.readFileSync(file.path) as Uint8Array : new Uint8Array(0));
634
658
  const at = (file.flags & flagBits().append) !== 0 ? existing.length
635
659
  : position === null || position === undefined || position < 0 ? file.position : position;
package/src/runtime.ts CHANGED
@@ -2410,10 +2410,28 @@ function createRequire(
2410
2410
  return loadModule(resolved).exports;
2411
2411
  };
2412
2412
 
2413
- require.resolve = (id: string): string => {
2413
+ require.resolve = (id: string, options?: { paths?: unknown }): string => {
2414
2414
  if (id === 'fs' || id === 'process' || id.startsWith('node:') || moduleShim.builtinModules.includes(id)) {
2415
2415
  return id;
2416
2416
  }
2417
+ // Node's `options.paths`: each directory, in order, is where the lookup starts, as if the request came from a
2418
+ // module there, and the first that resolves wins. The option was ignored and every lookup started at the caller,
2419
+ // so a module installed in one tree could not find a package another tree holds (a World's injector resolving
2420
+ // the application's own Prisma adapter from the application's directory). Node 12.
2421
+ if (options && options.paths !== undefined) {
2422
+ if (!Array.isArray(options.paths)) {
2423
+ throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options.paths)}`), { code: 'ERR_INVALID_ARG_VALUE' });
2424
+ }
2425
+ options.paths.forEach((from, index) => {
2426
+ if (typeof from !== 'string') throw Object.assign(new TypeError(`The "paths[${index}]" argument must be of type string. Received ${typeof from}`), { code: 'ERR_INVALID_ARG_TYPE' });
2427
+ });
2428
+ // A relative entry is the process's working directory's, as Node's Module._resolveFilename makes it.
2429
+ const requireStack = parentModule && typeof parentModule.filename === 'string' ? [parentModule.filename] : [];
2430
+ for (const from of options.paths as string[]) {
2431
+ try { return resolveModule(id, pathShim.resolve(process.cwd(), from)); } catch { /* the next directory */ }
2432
+ }
2433
+ throw Object.assign(new Error(`Cannot find module '${id}'${requireStack.length ? `\nRequire stack:\n- ${requireStack.join('\n- ')}` : ''}`), { code: 'MODULE_NOT_FOUND', requireStack });
2434
+ }
2417
2435
  return resolveModule(id, currentDir);
2418
2436
  };
2419
2437
 
package/src/virtual-fs.ts CHANGED
@@ -324,6 +324,9 @@ export class VirtualFS {
324
324
  if (existed && existing!.type === 'file') {
325
325
  existing!.content = content;
326
326
  existing!.mtime = Date.now();
327
+ // the caller's bytes, which it may still hold: never written in place
328
+ (existing as FSNode & { room?: Uint8Array; lent?: boolean }).room = undefined;
329
+ (existing as FSNode & { lent?: boolean }).lent = true;
327
330
  } else {
328
331
  parent.children!.set(basename, {
329
332
  type: 'file',
@@ -646,6 +649,10 @@ export class VirtualFS {
646
649
  return this.decoder.decode(content);
647
650
  }
648
651
 
652
+ // The bytes are handed out as they are, so a caller (a copy, a read
653
+ // stream's chunk) may hold them: a later write into the file does not
654
+ // change them in place (writeAtSync), it moves the file to bytes of its own.
655
+ (node as FSNode & { lent?: boolean }).lent = true;
649
656
  return content;
650
657
  }
651
658
 
@@ -698,6 +705,58 @@ export class VirtualFS {
698
705
  if (this.eventListeners.get('change')?.size) this.emit('change', normalized, this.decoder.decode(node.content));
699
706
  }
700
707
 
708
+ /**
709
+ * Bytes written into a file at `position`, as a disk takes them: a gap past
710
+ * the end reads as zeros, and the file grows in its own buffer as an append
711
+ * grows it. A database rewrites its log and its pages a page at a time;
712
+ * writing the whole file again for each page copied Postgres's 16 MB
713
+ * write-ahead log at every commit. A tree that keeps its files elsewhere
714
+ * (its own writeFileSync) is written through its own read and write unless
715
+ * it answers this itself.
716
+ */
717
+ writeAtSync(path: string, data: Uint8Array, position: number): void {
718
+ if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
719
+ const existing = this.existsSync(path) ? this.readFileSync(path) as Uint8Array : new Uint8Array(0);
720
+ if (data.byteLength === 0 && this.existsSync(path)) return;
721
+ const whole = new Uint8Array(Math.max(existing.byteLength, position + data.byteLength));
722
+ whole.set(existing, 0);
723
+ whole.set(data, position);
724
+ this.writeFileSync(path, whole);
725
+ return;
726
+ }
727
+ const normalized = this.normalizePath(path);
728
+ const node = this.getNode(normalized);
729
+ if (!node) {
730
+ const whole = new Uint8Array(position + data.byteLength);
731
+ whole.set(data, position);
732
+ this.writeFileSyncInternal(normalized, whole, true);
733
+ return;
734
+ }
735
+ if (node.type !== 'file') throw createNodeError('EISDIR', 'open', path);
736
+ this.assertWritable(normalized, 'open');
737
+ // Node's write of no bytes changes nothing, past the end included
738
+ if (data.byteLength === 0) return;
739
+ const current = node.content ?? new Uint8Array(0);
740
+ const length = Math.max(current.byteLength, position + data.byteLength);
741
+ const held = node as FSNode & { room?: Uint8Array; lent?: boolean };
742
+ let room = held.room;
743
+ // Written in place only into bytes the file owns and nobody else holds: a copy made from the file
744
+ // (writeFileSync(dest, readFileSync(src))) or a read's result shares them, and would change with it.
745
+ if (!room || held.lent || current.buffer !== room.buffer || current.byteOffset !== 0 || room.byteLength < length) {
746
+ room = new Uint8Array(Math.max(length, current.byteLength * 2, 4096));
747
+ room.set(current, 0);
748
+ held.lent = false;
749
+ } else if (position > current.byteLength) {
750
+ room.fill(0, current.byteLength, position);
751
+ }
752
+ room.set(data, position);
753
+ node.content = room.subarray(0, length);
754
+ (node as FSNode & { room?: Uint8Array }).room = room;
755
+ node.mtime = Date.now();
756
+ this.notifyWatchers(normalized, 'change');
757
+ if (this.eventListeners.get('change')?.size) this.emit('change', normalized, this.decoder.decode(node.content));
758
+ }
759
+
701
760
  /**
702
761
  * Create directory, optionally with recursive parent creation
703
762
  */