@poe-platform/safe-fs 0.1.803 → 0.1.805

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.
Files changed (40) hide show
  1. package/README.md +22 -4
  2. package/dist/safe-fs/bridge/filesystem.js +1 -1
  3. package/dist/safe-fs/contracts/errors.d.ts +1 -0
  4. package/dist/safe-fs/contracts/errors.js +16 -3
  5. package/dist/safe-fs/contracts/filesystem.d.ts +3 -2
  6. package/dist/safe-fs/contracts/io.d.ts +2 -0
  7. package/dist/safe-fs/contracts/io.js +32 -7
  8. package/dist/safe-fs/contracts/portable-path.d.ts +8 -0
  9. package/dist/safe-fs/contracts/portable-path.js +22 -1
  10. package/dist/safe-fs/core.d.ts +3 -14
  11. package/dist/safe-fs/core.js +3 -11
  12. package/dist/safe-fs/fs/devices/index.d.ts +6 -1
  13. package/dist/safe-fs/fs/devices/index.js +40 -24
  14. package/dist/safe-fs/fs/devices/path.js +1 -1
  15. package/dist/safe-fs/fs/directory-admission.js +2 -2
  16. package/dist/safe-fs/fs/memory/atomic-view.d.ts +3 -0
  17. package/dist/safe-fs/fs/memory/atomic-view.js +5 -0
  18. package/dist/safe-fs/fs/memory/index.d.ts +6 -3
  19. package/dist/safe-fs/fs/memory/index.js +147 -131
  20. package/dist/safe-fs/fs/memory/ledger.js +3 -1
  21. package/dist/safe-fs/fs/memory/limits.js +3 -0
  22. package/dist/safe-fs/fs/mount/comparison.js +3 -3
  23. package/dist/safe-fs/fs/object-publication/index.js +2 -1
  24. package/dist/safe-fs/fs/readonly/index.js +1 -1
  25. package/dist/safe-fs/fs/real/index.js +3 -2
  26. package/dist/safe-fs/fs/s3/filesystem.js +1 -1
  27. package/dist/safe-fs/fs/s3/http/request-fetch.d.ts +14 -3
  28. package/dist/safe-fs/fs/s3/http/request-node.d.ts +2 -2
  29. package/dist/safe-fs/fs/s3/http/types.d.ts +2 -2
  30. package/dist/safe-fs/fs/s3/manifest-admission.js +0 -4
  31. package/dist/safe-fs/fs/s3/namespace.js +2 -4
  32. package/dist/safe-fs/fs/webdav/webdav.js +5 -29
  33. package/dist/safe-fs/fs/webdav/xml.js +2 -2
  34. package/dist/safe-fs/python/emscripten.js +5 -2
  35. package/dist/safe-fs/python/filesystem.js +2 -2
  36. package/dist/safe-fs/python/native.js +1 -1
  37. package/dist/safe-fs/python/stat.js +5 -2
  38. package/dist/safe-fs/runtime-core.d.ts +26 -0
  39. package/dist/safe-fs/runtime-core.js +56 -0
  40. package/package.json +16 -2
@@ -9,7 +9,7 @@ import { directoryAncestryPaths, runStagingGuard, snapshotDirectoryAncestry, sna
9
9
  import { compareIdentity } from "../mount/identity.js";
10
10
  import { createStagingCleanup, snapshotStagingCreation } from "../staging-cleanup.js";
11
11
  import { resolveMissingTarget } from "./missing-target.js";
12
- import { registerMemoryAtomicView } from "./atomic-view.js";
12
+ import { registerLazyMemoryAtomicView } from "./atomic-view.js";
13
13
  import { snapshotConditionalChmod } from "../conditional-chmod.js";
14
14
  import { MemoryAllocation, MemoryLedger } from "./ledger.js";
15
15
  import { normalizeMemoryFileSystemLimits } from "./limits.js";
@@ -46,24 +46,21 @@ Object.assign(MemoryFileNode.prototype, {
46
46
  sourceRef: undefined,
47
47
  });
48
48
  const EMPTY_ALLOC_BYTES = new Uint8Array(0);
49
- const SMALL_ALLOC_SLAB_SIZE = 8192;
50
- let smallAllocSlab = new Uint8Array(SMALL_ALLOC_SLAB_SIZE);
51
- let smallAllocOffset = 0;
52
49
  const DUMMY_POOL_LEDGER = new MemoryLedger(normalizeMemoryFileSystemLimits({}));
53
50
  const DUMMY_POOL_ALLOCATION = new MemoryAllocation(EMPTY_ALLOC_BYTES, DUMMY_POOL_LEDGER);
54
51
  const DUMMY_POOL_FILE_NODE = new MemoryFileNode(0, 0, null, 0, DUMMY_POOL_ALLOCATION, DUMMY_POOL_ALLOCATION.data);
55
52
  DUMMY_POOL_FILE_NODE.atimeMs = DUMMY_POOL_FILE_NODE.mtimeMs = DUMMY_POOL_FILE_NODE.ctimeMs = DUMMY_POOL_FILE_NODE.birthtimeMs = 1700000000000;
56
- const defaultDateNow = Date.now;
57
- let fastWriteCachedNow = Date.now();
58
- let fastWriteNowTick = 0;
53
+ const EMPTY_DIR_TABLE = new Int16Array(0);
54
+ const EMPTY_DIR_KEYS = [];
55
+ const EMPTY_DIR_VALS = [];
59
56
  class FastDirectoryEntriesMap {
60
57
  // Keep speculative slots local so a failed write cannot pin a tenant globally.
61
58
  _missKey = "";
62
59
  _missSlot = -1;
63
- _table = new Int16Array(128).fill(-1);
64
- _mask = 127;
65
- _keys = new Array(64).fill("");
66
- _vals = new Array(64).fill(DUMMY_POOL_FILE_NODE);
60
+ _table = EMPTY_DIR_TABLE;
61
+ _mask = 0;
62
+ _keys = EMPTY_DIR_KEYS;
63
+ _vals = EMPTY_DIR_VALS;
67
64
  _next = 0;
68
65
  size = 0;
69
66
  [Symbol.toStringTag] = "Map";
@@ -96,6 +93,11 @@ class FastDirectoryEntriesMap {
96
93
  getForWriteWithHash(k, h) {
97
94
  let slot = h & this._mask;
98
95
  if (this.size === 0) {
96
+ if (this._keys.length === 0) {
97
+ this._missKey = "";
98
+ this._missSlot = -1;
99
+ return undefined;
100
+ }
99
101
  this._missKey = k;
100
102
  this._missSlot = slot;
101
103
  return undefined;
@@ -211,7 +213,7 @@ class FastDirectoryEntriesMap {
211
213
  return this;
212
214
  }
213
215
  if (this._next >= this._keys.length) {
214
- this._rebuild(this.size * 2 <= this._keys.length ? this._keys.length : this._keys.length * 2);
216
+ this._rebuild(this._keys.length === 0 ? 8 : (this.size * 2 <= this._keys.length ? this._keys.length : this._keys.length * 2));
215
217
  }
216
218
  let slot = this._hash(k);
217
219
  const mask = this._mask;
@@ -350,19 +352,13 @@ function collectRemovedChild(child, name) {
350
352
  }
351
353
  function replenishSharedMemoryPools() {
352
354
  while (sharedAllocationPoolLen < 112) {
353
- if (smallAllocOffset + 64 > SMALL_ALLOC_SLAB_SIZE) {
354
- smallAllocSlab = new Uint8Array(SMALL_ALLOC_SLAB_SIZE);
355
- smallAllocOffset = 0;
356
- }
357
- const slice = smallAllocSlab.subarray(smallAllocOffset, smallAllocOffset + 64);
358
- smallAllocOffset += 64;
359
355
  DUMMY_POOL_LEDGER.reserve(64, 0, "init", "/");
360
- const alloc = new MemoryAllocation(slice, DUMMY_POOL_LEDGER);
356
+ const alloc = new MemoryAllocation(new Uint8Array(64), DUMMY_POOL_LEDGER);
361
357
  alloc.release();
362
358
  sharedAllocationPool[sharedAllocationPoolLen++] = alloc;
363
359
  }
364
360
  while (sharedFileNodePoolLen < 112) {
365
- sharedFileNodePool[sharedFileNodePoolLen++] = new MemoryFileNode(0, 0, fastWriteCachedNow, 0, DUMMY_POOL_ALLOCATION, undefined);
361
+ sharedFileNodePool[sharedFileNodePoolLen++] = new MemoryFileNode(0, 0, 0, 0, DUMMY_POOL_ALLOCATION, undefined);
366
362
  }
367
363
  while (sharedLargeAllocationPoolLen < 4) {
368
364
  DUMMY_POOL_LEDGER.reserve(65536, 0, "init", "/");
@@ -377,7 +373,7 @@ function replenishSharedMemoryPools() {
377
373
  sharedMediumAllocationPool[sharedMediumAllocationPoolLen++] = alloc;
378
374
  }
379
375
  while (sharedDirectoryNodePoolLen < 16) {
380
- sharedDirectoryNodePool[sharedDirectoryNodePoolLen++] = new MemoryDirectoryNode(0, 0, fastWriteCachedNow);
376
+ sharedDirectoryNodePool[sharedDirectoryNodePoolLen++] = new MemoryDirectoryNode(0, 0, 0);
381
377
  }
382
378
  }
383
379
  class MemoryDirectoryNode {
@@ -427,7 +423,6 @@ class MemoryCache {
427
423
  const typeModes = { file: 0o100000, directory: 0o040000, symlink: 0o120000 };
428
424
  const emptyResolveOptions = Object.freeze({});
429
425
  const noFollowResolveOptions = Object.freeze({ followFinal: false });
430
- const sharedMkdirResolveOptions = { createDirectories: 0o777 };
431
426
  const sharedAllowMissingNoFollowOptions = Object.freeze({ allowMissing: true, followFinal: false });
432
427
  const sharedFastLocation = { node: undefined, parent: DUMMY_POOL_DIR_NODE, name: "", path: "" };
433
428
  const resolvedVoid = Promise.resolve();
@@ -453,7 +448,7 @@ const compareOwnedMemory = async (own, peer, options) => {
453
448
  let answer = "unknown";
454
449
  const visited = new Set();
455
450
  for (const [left, right] of [[own, peer], [peer, own]]) {
456
- if (!registeredAuthorities.has(left.filesystem) || visited.has(left.filesystem))
451
+ if ((!registeredAuthorities.has(left.filesystem) && !ownedStores.has(left.filesystem)) || visited.has(left.filesystem))
457
452
  continue;
458
453
  visited.add(left.filesystem);
459
454
  const comparison = left.filesystem.compareEntry;
@@ -602,32 +597,48 @@ class MemoryReadStream {
602
597
  return STREAM_RESOLVED_DONE;
603
598
  }
604
599
  }
600
+ const SHARED_STOCK_MEMORY_CAPABILITIES = Object.freeze({
601
+ read: true, stat: true, readdir: true, realpath: true, access: true, open: true,
602
+ write: true, append: true, exclusiveCreate: true, explicitDirectories: true, implicitDirectories: false,
603
+ mkdir: true, recursiveMkdir: true, remove: true, removeDirectory: true, recursiveRemove: true,
604
+ rename: true, atomicRenameNoReplace: true, copy: true, exclusiveCopy: true, readlink: true, truncate: true,
605
+ streamingAppend: true, randomAccessWrite: true,
606
+ readOnly: false,
607
+ symlinks: true, conditionalChmod: true,
608
+ hardlinks: true,
609
+ permissions: true,
610
+ timestamps: true,
611
+ atomicRename: true,
612
+ atomicFileStaging: true, retainedStagingCleanup: true, retainedStagingWrite: true, atomicStagingAncestry: true, atomicFileMutation: true, atomicEntryRemoval: true, atomicEntryRemovalReceipt: true, atomicTreeRemoval: true,
613
+ synchronousDirectoryValidation: true, synchronousStagingResolution: true, guardedStagingPublication: true,
614
+ atomicDirectoryMetadata: true,
615
+ streamingRead: true,
616
+ retainedRead: true,
617
+ retainedResize: true,
618
+ streamingWrite: true,
619
+ descriptorWriteStream: true,
620
+ });
621
+ function customMemoryCapabilities(filesystem) {
622
+ return Object.freeze({
623
+ ...SHARED_STOCK_MEMORY_CAPABILITIES,
624
+ get retainedResize() { return stockRetainedResize(filesystem); },
625
+ get descriptorWriteStream() { return stockDescriptorWrite(filesystem); },
626
+ });
627
+ }
605
628
  export class MemoryFileSystem {
606
629
  capabilitiesFor;
607
- capabilities = ((filesystem) => {
608
- return Object.freeze({
609
- read: true, stat: true, readdir: true, realpath: true, access: true, open: true,
610
- write: true, append: true, exclusiveCreate: true, explicitDirectories: true, implicitDirectories: false,
611
- mkdir: true, recursiveMkdir: true, remove: true, removeDirectory: true, recursiveRemove: true,
612
- rename: true, atomicRenameNoReplace: true, copy: true, exclusiveCopy: true, readlink: true, truncate: true,
613
- streamingAppend: true, randomAccessWrite: true,
614
- readOnly: false,
615
- symlinks: true, conditionalChmod: true,
616
- hardlinks: true,
617
- permissions: true,
618
- timestamps: true,
619
- atomicRename: true,
620
- atomicFileStaging: true, retainedStagingCleanup: true, retainedStagingWrite: true, atomicStagingAncestry: true, atomicFileMutation: true, atomicEntryRemoval: true, atomicEntryRemovalReceipt: true, atomicTreeRemoval: true,
621
- synchronousDirectoryValidation: true, synchronousStagingResolution: true, guardedStagingPublication: true,
622
- atomicDirectoryMetadata: true,
623
- streamingRead: true,
624
- retainedRead: true,
625
- get retainedResize() { return stockRetainedResize(filesystem); },
626
- streamingWrite: true,
627
- get descriptorWriteStream() { return stockDescriptorWrite(filesystem); },
628
- });
629
- })(this);
630
- identityScope = Symbol();
630
+ #customCapabilities;
631
+ #identityScopeSym;
632
+ get identityScope() {
633
+ return (this.#identityScopeSym ??= Symbol());
634
+ }
635
+ get capabilities() {
636
+ if (!this.#customCapabilities) {
637
+ this.#customCapabilities = customMemoryCapabilities(this);
638
+ this._owner.capabilities = this.#customCapabilities;
639
+ }
640
+ return this.#customCapabilities;
641
+ }
631
642
  nextInode = 1;
632
643
  ledger;
633
644
  _cache;
@@ -636,26 +647,34 @@ export class MemoryFileSystem {
636
647
  root;
637
648
  totalBytes = 0;
638
649
  symlinkCount = 0;
639
- constructor(options = {}) {
640
- this.ledger = new MemoryLedger(normalizeMemoryFileSystemLimits(options));
641
- if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes) {
642
- replenishSharedMemoryPools();
650
+ #atomicView;
651
+ _getAtomicView() {
652
+ const owner = ownedStores.get(this);
653
+ if (!owner ||
654
+ Object.getPrototypeOf(this) !== MemoryFileSystem.prototype ||
655
+ this.root !== owner.root ||
656
+ this.ledger !== owner.ledger ||
657
+ this.capabilities !== owner.capabilities) {
658
+ return undefined;
643
659
  }
644
- const cache = new MemoryCache();
645
- this._cache = cache;
646
- memoryCaches.set(this.ledger, cache);
647
- this.ledger.reserve(0, 1, "mkdir", "/");
648
- this.root = this.directory(0o755);
649
- const root = this.root;
650
- const owner = {
651
- root,
652
- ledger: this.ledger,
653
- capabilities: this.capabilities,
654
- intact: () => this.root === root,
655
- };
656
- this._owner = owner;
657
- ownedStores.set(this, owner);
658
- registerMemoryAtomicView(this, {
660
+ const proto = MemoryFileSystem.prototype;
661
+ for (let i = 0; i < memoryImplementationKeys.length; i++) {
662
+ const name = memoryImplementationKeys[i];
663
+ const expected = memoryImplementationDescriptors[i];
664
+ if (name === "capabilities")
665
+ continue;
666
+ if (Object.prototype.hasOwnProperty.call(this, name)) {
667
+ const actual = Object.getOwnPropertyDescriptor(this, name);
668
+ if (!actual || actual.value !== expected.value || actual.get !== expected.get || actual.set !== expected.set)
669
+ return undefined;
670
+ }
671
+ else if (expected.get !== undefined || expected.set !== undefined || proto[name] !== expected.value) {
672
+ const actual = Object.getOwnPropertyDescriptor(MemoryFileSystem.prototype, name);
673
+ if (!actual || actual.value !== expected.value || actual.get !== expected.get || actual.set !== expected.set)
674
+ return undefined;
675
+ }
676
+ }
677
+ return this.#atomicView ??= {
659
678
  stat: (path) => {
660
679
  this.validatePath(path, "overlayAtomicView");
661
680
  let node = this.root;
@@ -677,30 +696,28 @@ export class MemoryFileSystem {
677
696
  this.fail("ENOTDIR", "overlayAtomicView", path);
678
697
  return [...node.entries.keys()];
679
698
  },
680
- }, () => {
681
- if (Object.getPrototypeOf(this) !== MemoryFileSystem.prototype ||
682
- this.root !== root ||
683
- this.ledger !== ownedStores.get(this)?.ledger ||
684
- this.capabilities !== ownedStores.get(this)?.capabilities) {
685
- return false;
686
- }
687
- const proto = MemoryFileSystem.prototype;
688
- for (let i = 0; i < memoryImplementationKeys.length; i++) {
689
- const name = memoryImplementationKeys[i];
690
- const expected = memoryImplementationDescriptors[i];
691
- if (Object.prototype.hasOwnProperty.call(this, name)) {
692
- const actual = Object.getOwnPropertyDescriptor(this, name);
693
- if (!actual || actual.value !== expected.value || actual.get !== expected.get || actual.set !== expected.set)
694
- return false;
695
- }
696
- else if (expected.get !== undefined || expected.set !== undefined || proto[name] !== expected.value) {
697
- const actual = Object.getOwnPropertyDescriptor(MemoryFileSystem.prototype, name);
698
- if (!actual || actual.value !== expected.value || actual.get !== expected.get || actual.set !== expected.set)
699
- return false;
700
- }
701
- }
702
- return true;
703
- });
699
+ };
700
+ }
701
+ constructor(options = {}) {
702
+ this.ledger = new MemoryLedger(normalizeMemoryFileSystemLimits(options));
703
+ if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes) {
704
+ replenishSharedMemoryPools();
705
+ }
706
+ const cache = new MemoryCache();
707
+ this._cache = cache;
708
+ memoryCaches.set(this.ledger, cache);
709
+ this.ledger.reserve(0, 1, "mkdir", "/");
710
+ this.root = this.directory(0o755);
711
+ const root = this.root;
712
+ const owner = {
713
+ root,
714
+ ledger: this.ledger,
715
+ capabilities: SHARED_STOCK_MEMORY_CAPABILITIES,
716
+ intact: () => this.root === root,
717
+ };
718
+ this._owner = owner;
719
+ ownedStores.set(this, owner);
720
+ registerLazyMemoryAtomicView(this, memoryImplementation._getAtomicView.value);
704
721
  if (this.compareEntry === memoryImplementation.compareEntry?.value) {
705
722
  registeredAuthorities.add(this);
706
723
  registerEntryAuthority(this, compareOwnedMemory);
@@ -897,7 +914,6 @@ export class MemoryFileSystem {
897
914
  if (alloc.isReleased64()) {
898
915
  alloc.detachLedger(DUMMY_POOL_LEDGER);
899
916
  if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes && sharedAllocationPoolLen < SHARED_POOL_CAPACITY) {
900
- alloc.data.fill(0);
901
917
  sharedAllocationPool[sharedAllocationPoolLen++] = alloc;
902
918
  }
903
919
  else if (cache.allocations.length < 128) {
@@ -907,7 +923,6 @@ export class MemoryFileSystem {
907
923
  else if (alloc.isReleased65536()) {
908
924
  alloc.detachLedger(DUMMY_POOL_LEDGER);
909
925
  if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes && sharedLargeAllocationPoolLen < SHARED_LARGE_POOL_CAPACITY) {
910
- alloc.data.fill(0);
911
926
  sharedLargeAllocationPool[sharedLargeAllocationPoolLen++] = alloc;
912
927
  }
913
928
  }
@@ -953,14 +968,12 @@ export class MemoryFileSystem {
953
968
  if (previous.isReleased64()) {
954
969
  previous.detachLedger(DUMMY_POOL_LEDGER);
955
970
  if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes && sharedAllocationPoolLen < SHARED_POOL_CAPACITY) {
956
- previous.data.fill(0);
957
971
  sharedAllocationPool[sharedAllocationPoolLen++] = previous;
958
972
  }
959
973
  }
960
974
  else if (previous.isReleased65536()) {
961
975
  previous.detachLedger(DUMMY_POOL_LEDGER);
962
976
  if (this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes && sharedLargeAllocationPoolLen < SHARED_LARGE_POOL_CAPACITY) {
963
- previous.data.fill(0);
964
977
  sharedLargeAllocationPool[sharedLargeAllocationPoolLen++] = previous;
965
978
  }
966
979
  }
@@ -1372,17 +1385,6 @@ export class MemoryFileSystem {
1372
1385
  }
1373
1386
  }
1374
1387
  try {
1375
- // A shared slab's backing buffer exceeds the admitted slice capacity.
1376
- // Finite file/storage ceilings require independently owned exact buffers.
1377
- if (length <= 64 && this.ledger.hasInfiniteRetained && this.ledger.hasInfiniteFileBytes) {
1378
- if (smallAllocOffset + length > SMALL_ALLOC_SLAB_SIZE) {
1379
- smallAllocSlab = new Uint8Array(SMALL_ALLOC_SLAB_SIZE);
1380
- smallAllocOffset = 0;
1381
- }
1382
- const slice = smallAllocSlab.subarray(smallAllocOffset, smallAllocOffset + length);
1383
- smallAllocOffset += length;
1384
- return new MemoryAllocation(slice, this.ledger);
1385
- }
1386
1388
  return new MemoryAllocation(new Uint8Array(length), this.ledger);
1387
1389
  }
1388
1390
  catch (cause) {
@@ -1568,11 +1570,12 @@ export class MemoryFileSystem {
1568
1570
  }
1569
1571
  if (position > curLen)
1570
1572
  storage.fill(0, curLen, position);
1573
+ const source = data;
1571
1574
  if (dataLen === data.byteLength) {
1572
1575
  storage.set(data, position);
1573
1576
  }
1574
- else if (typeof data.copy === "function") {
1575
- data.copy(storage, position, 0, dataLen);
1577
+ else if (typeof source.copy === "function") {
1578
+ source.copy(storage, position, 0, dataLen);
1576
1579
  }
1577
1580
  else {
1578
1581
  for (let i = 0; i < dataLen; i++)
@@ -1771,7 +1774,7 @@ export class MemoryFileSystem {
1771
1774
  1 + batchCount <= entries._keys.length) {
1772
1775
  this.ledger.reserve(totalNameBytes, 2 * batchCount, "writeFile", fileNames[batchCount - 1]);
1773
1776
  this.totalBytes += payloadBytesSum;
1774
- const now = fastWriteCachedNow;
1777
+ const now = Date.now();
1775
1778
  const fileMode = typeModes.file | mode;
1776
1779
  let ino = this.nextInode;
1777
1780
  this.nextInode = ino + batchCount;
@@ -1844,7 +1847,7 @@ export class MemoryFileSystem {
1844
1847
  const existing = nameHash !== undefined ? entries.getForWriteWithHash(name, nameHash) : entries.getForWrite(name);
1845
1848
  if (existing === undefined && entries._next < entries._keys.length) {
1846
1849
  this.ledger.reserve(name.length * 2, 2, "writeFile", name);
1847
- const now = fastWriteCachedNow;
1850
+ const now = Date.now();
1848
1851
  const length = data.byteLength;
1849
1852
  const node = sharedFileNodePool[--sharedFileNodePoolLen];
1850
1853
  sharedFileNodePool[sharedFileNodePoolLen] = DUMMY_POOL_FILE_NODE;
@@ -1966,7 +1969,7 @@ export class MemoryFileSystem {
1966
1969
  allocation.data.set(data);
1967
1970
  this.ledger.reserve(nameBytes, 2, syscall, name);
1968
1971
  try {
1969
- const now = fastWriteCachedNow;
1972
+ const now = Date.now();
1970
1973
  const fileMode = typeModes.file | mode;
1971
1974
  const view = zeroCopyConst ? new Uint8Array(data) : (capacity === length ? allocation.data : undefined);
1972
1975
  let node;
@@ -2047,7 +2050,7 @@ export class MemoryFileSystem {
2047
2050
  }
2048
2051
  async readFile(path, options = {}) {
2049
2052
  options.signal?.throwIfAborted();
2050
- if (options.maxBytes !== undefined)
2053
+ if (options.maxBytes !== undefined && options.maxBytes !== Infinity)
2051
2054
  this.integer(options.maxBytes, "readFile", path);
2052
2055
  const node = this.file(path, "readFile");
2053
2056
  this.permission(node, 4, "readFile", path);
@@ -2922,7 +2925,10 @@ export class MemoryFileSystem {
2922
2925
  if (!descriptor || !("value" in descriptor) || descriptor.value !== memoryImplementation[name]?.value)
2923
2926
  unsupported();
2924
2927
  }
2925
- const retainedRead = Object.getOwnPropertyDescriptor(this, "capabilities")?.value?.retainedRead;
2928
+ const capabilities = Object.getOwnPropertyDescriptor(this, "capabilities");
2929
+ const retainedRead = capabilities === undefined
2930
+ ? Object.getOwnPropertyDescriptor(MemoryFileSystem.prototype, "capabilities")?.get === memoryImplementation.capabilities?.get
2931
+ : capabilities.value?.retainedRead;
2926
2932
  signal?.throwIfAborted();
2927
2933
  if (retainedRead !== true)
2928
2934
  unsupported();
@@ -3062,7 +3068,7 @@ function stockDescriptorWrite(filesystem) {
3062
3068
  return false;
3063
3069
  const owner = ownedStores.get(filesystem);
3064
3070
  const capDesc = Object.getOwnPropertyDescriptor(filesystem, "capabilities");
3065
- return !!capDesc && "value" in capDesc && capDesc.value === owner.capabilities;
3071
+ return (capDesc === undefined && Object.getOwnPropertyDescriptor(MemoryFileSystem.prototype, "capabilities")?.get === memoryImplementation.capabilities?.get) || (!!capDesc && "value" in capDesc && capDesc.value === owner.capabilities);
3066
3072
  }
3067
3073
  function stockRetainedResize(filesystem) {
3068
3074
  if (!stockDescriptorWrite(filesystem) || !isStockMemoryMethods(filesystem, stockRetainedResizeMethodNames, false))
@@ -3120,7 +3126,7 @@ export class MemoryRedirectHandle {
3120
3126
  if (len === 0)
3121
3127
  return;
3122
3128
  const pos = this.append ? this.node.byteLength : this.position;
3123
- const now = Date.now === defaultDateNow ? fastWriteCachedNow : Date.now();
3129
+ const now = Date.now();
3124
3130
  this.fs.writeAtRange(this.node, src, len, pos, "write", this.path, now);
3125
3131
  if (!this.append)
3126
3132
  this.position = pos + len;
@@ -3140,7 +3146,7 @@ export class MemoryRedirectHandle {
3140
3146
  mem.ledger.hasInfiniteRetained &&
3141
3147
  mem.ledger.hasInfiniteFileBytes &&
3142
3148
  mem.ledger.limits.maxBytes === undefined) {
3143
- const now = Date.now === defaultDateNow ? fastWriteCachedNow : Date.now();
3149
+ const now = Date.now();
3144
3150
  this.node.byteLength = len;
3145
3151
  this.node.view = immutableData;
3146
3152
  this.node.sourceRef = immutableData;
@@ -3266,7 +3272,7 @@ export function tryOpenMemoryRedirectHandleSync(filesystem, path, append, mode,
3266
3272
  }
3267
3273
  const cache = mem._cache;
3268
3274
  cache.clearWrites();
3269
- const now = Date.now === defaultDateNow ? ((++fastWriteNowTick & 63) === 0 ? (fastWriteCachedNow = Date.now()) : fastWriteCachedNow) : Date.now();
3275
+ const now = Date.now();
3270
3276
  const fileMode = typeModes.file | validMode;
3271
3277
  let newNode;
3272
3278
  if (sharedFileNodePoolLen > 0) {
@@ -3421,7 +3427,7 @@ export function tryResolveMemoryDevicePath(filesystem, path, resizeCreate) {
3421
3427
  start = slash + 1;
3422
3428
  }
3423
3429
  }
3424
- const cachedMethodValuesMap = new WeakMap();
3430
+ const cachedMethodValuesMap = /* @__PURE__ */ new WeakMap();
3425
3431
  function getExpectedMethodValues(names) {
3426
3432
  let vals = cachedMethodValuesMap.get(names);
3427
3433
  if (!vals) {
@@ -3467,7 +3473,7 @@ export function getLastReadMemoryFileSourceRef(view) {
3467
3473
  lastReadViewSourceRef = undefined;
3468
3474
  return ref;
3469
3475
  }
3470
- export function tryReadMemoryFileViewSync(filesystem, path, maxBytes, signal, captureSourceRef = false) {
3476
+ export function tryReadMemoryFileViewSync(filesystem, path, maxBytes, signal, captureSourceRef = false, beforeRead) {
3471
3477
  // A capture belongs only to the most recent read, including failed/fallback reads.
3472
3478
  lastReadViewData = undefined;
3473
3479
  lastReadViewSourceRef = undefined;
@@ -3475,19 +3481,15 @@ export function tryReadMemoryFileViewSync(filesystem, path, maxBytes, signal, ca
3475
3481
  if (mem._owner === undefined || !isStockMemoryMethods(mem, readFileFastMethodNames, false))
3476
3482
  return undefined;
3477
3483
  signal?.throwIfAborted();
3478
- if (maxBytes !== undefined)
3484
+ beforeRead?.();
3485
+ if (maxBytes !== undefined && maxBytes !== Infinity)
3479
3486
  mem.integer(maxBytes, "readFile", path);
3480
3487
  const node = mem.file(path, "readFile");
3481
3488
  mem.permission(node, 4, "readFile", path);
3482
3489
  const data = node.data;
3483
3490
  if (maxBytes !== undefined && data.byteLength > maxBytes)
3484
3491
  mem.fail("EFBIG", "readFile", path);
3485
- if (Date.now !== defaultDateNow)
3486
- node.atimeMs = Date.now();
3487
- else if ((++fastWriteNowTick & 63) === 0)
3488
- node.atimeMs = fastWriteCachedNow = Date.now();
3489
- else
3490
- node.atimeMs = fastWriteCachedNow;
3492
+ node.atimeMs = Date.now();
3491
3493
  if (captureSourceRef && node.revision === 0) {
3492
3494
  lastReadViewData = new WeakRef(data);
3493
3495
  lastReadViewSourceRef = node.sourceRef === undefined ? undefined : new WeakRef(node.sourceRef);
@@ -3570,7 +3572,7 @@ export function tryGetMemoryDirectoryEntryNamesSync(filesystem, path) {
3570
3572
  validatePath(path, owner.ledger.limits);
3571
3573
  const root = mem.root;
3572
3574
  if (path === "/") {
3573
- if (((root.mode >> 6) & 4) !== 4)
3575
+ if (((root.mode >> 6) & 5) !== 5)
3574
3576
  return undefined;
3575
3577
  return root.entries;
3576
3578
  }
@@ -3581,7 +3583,7 @@ export function tryGetMemoryDirectoryEntryNamesSync(filesystem, path) {
3581
3583
  const fastPrefix = cache?.lastFastDirPrefix;
3582
3584
  if (fastDir !== undefined &&
3583
3585
  fastDir.nlink !== 0 &&
3584
- ((fastDir.mode >> 6) & 4) === 4 &&
3586
+ ((fastDir.mode >> 6) & 5) === 5 &&
3585
3587
  fastPrefix !== undefined &&
3586
3588
  (fastPrefix === path || (fastPrefix.length === path.length + 1 && fastPrefix.charCodeAt(path.length) === 47 && fastPrefix.startsWith(path)))) {
3587
3589
  return fastDir.entries;
@@ -3594,7 +3596,7 @@ export function tryGetMemoryDirectoryEntryNamesSync(filesystem, path) {
3594
3596
  const slash = path.indexOf("/", start);
3595
3597
  if (slash === -1) {
3596
3598
  const next = current.entries.getSubstr(path, start, path.length);
3597
- if (!next || next.type !== "directory" || ((next.mode >> 6) & 4) !== 4)
3599
+ if (!next || next.type !== "directory" || ((next.mode >> 6) & 5) !== 5)
3598
3600
  return undefined;
3599
3601
  return next.entries;
3600
3602
  }
@@ -3648,7 +3650,7 @@ export function tryMkdirMemorySync(filesystem, path, recursive, mode, signal, di
3648
3650
  let next = current.entries.get(seg);
3649
3651
  if (!next) {
3650
3652
  mem.permission(current, 3, "mkdir", path);
3651
- next = mem.addDirectoryNode(current, seg, validMode, "mkdir", path, fastWriteCachedNow);
3653
+ next = mem.addDirectoryNode(current, seg, validMode, "mkdir", path, Date.now());
3652
3654
  }
3653
3655
  else if (next.type !== "directory") {
3654
3656
  mem.fail(slash === -1 ? "EEXIST" : "ENOTDIR", "mkdir", path);
@@ -3669,7 +3671,7 @@ export function tryMkdirMemorySync(filesystem, path, recursive, mode, signal, di
3669
3671
  if (location.node)
3670
3672
  mem.fail("EEXIST", "mkdir", path);
3671
3673
  mem.permission(location.parent, 3, "mkdir", path);
3672
- mem.addDirectoryNode(location.parent, location.name, validMode, "mkdir", path, fastWriteCachedNow);
3674
+ mem.addDirectoryNode(location.parent, location.name, validMode, "mkdir", path, Date.now());
3673
3675
  return true;
3674
3676
  }
3675
3677
  export function tryRmRfMemorySync(filesystem, path, signal) {
@@ -3719,7 +3721,7 @@ export function tryRmRfMemorySync(filesystem, path, signal) {
3719
3721
  sharedFastLocation.name = targetName;
3720
3722
  sharedFastLocation.path = path;
3721
3723
  try {
3722
- mem.removeLocation(sharedFastLocation, path, "rm", true, fastWriteCachedNow);
3724
+ mem.removeLocation(sharedFastLocation, path, "rm", true, Date.now());
3723
3725
  }
3724
3726
  finally {
3725
3727
  sharedFastLocation.node = undefined;
@@ -3748,3 +3750,17 @@ export function tryWriteMemoryFileInDirSync(filesystem, dirPrefix, name, data, a
3748
3750
  mem.writeMemoryFileInDirFast(dirPrefix, name, data, append, mode);
3749
3751
  return true;
3750
3752
  }
3753
+ const _memHooks = (globalThis.__safeBashMemHooks ??= { protos: new Set(), byProto: new Map() });
3754
+ _memHooks.protos.add(MemoryFileSystem.prototype);
3755
+ _memHooks.byProto.set(MemoryFileSystem.prototype, {
3756
+ tryGetMemoryDirectoryEntryNamesSync,
3757
+ tryReadMemoryFileViewSync,
3758
+ tryResolveMemoryDevicePath,
3759
+ tryOpenMemoryRedirectHandleSync,
3760
+ tryWriteMemoryFileSync,
3761
+ tryMkdirMemorySync,
3762
+ tryRmRfMemorySync,
3763
+ tryWriteMemoryFileInDirSync,
3764
+ });
3765
+ _memHooks.isCleanAbsolutePath = isCleanAbsolutePath;
3766
+ _memHooks.bindConditionalMutation = bindConditionalMutation;
@@ -84,8 +84,10 @@ export class MemoryAllocation {
84
84
  return;
85
85
  if (this.references <= 0)
86
86
  throw new Error("Memory allocation already released");
87
- if (--this.references === 0)
87
+ if (--this.references === 0) {
88
+ this.data.fill(0);
88
89
  this.ledger.release(this.data.byteLength, 0);
90
+ }
89
91
  }
90
92
  isReleased64() {
91
93
  return this.references === 0 && this.data.byteLength === 64;
@@ -7,6 +7,9 @@ export const defaultMemoryFileSystemLimits = Object.freeze({
7
7
  maxMetadataUnits: Infinity,
8
8
  });
9
9
  export function normalizeMemoryFileSystemLimits(options) {
10
+ if (options === undefined || (typeof options === "object" && options !== null && Object.getPrototypeOf(options) === Object.prototype && Reflect.ownKeys(options).length === 0)) {
11
+ return defaultMemoryFileSystemLimits;
12
+ }
10
13
  const keys = ["maxPathBytes", "maxPathComponents", "maxFileBytes", "maxRetainedBytes", "maxMetadataUnits"];
11
14
  const record = readConfigRecord(options, "memory option", [...keys, "maxBytes"]);
12
15
  const limits = { ...defaultMemoryFileSystemLimits };
@@ -29,7 +29,7 @@ export async function resolveEntryView(filesystem, path, options = {}) {
29
29
  readOnly ||= location.readOnly === true || location.filesystem.capabilities.readOnly === true;
30
30
  if (location.stat)
31
31
  return { filesystem: location.filesystem, path: location.path, stat: location.stat, readOnly };
32
- const resolve = resolvers.get(location.filesystem);
32
+ const resolve = resolvers.get(location.filesystem) ?? location.filesystem._resolveEntryView;
33
33
  if (!resolve) {
34
34
  let stat;
35
35
  let followedPath;
@@ -49,7 +49,7 @@ export async function resolveEntryView(filesystem, path, options = {}) {
49
49
  }
50
50
  let next;
51
51
  try {
52
- next = await resolve(location.path, options);
52
+ next = await resolve.call(location.filesystem, location.path, options);
53
53
  }
54
54
  catch (error) {
55
55
  options.signal?.throwIfAborted();
@@ -74,7 +74,7 @@ export async function compareResolvedEntries(own, peer, options = {}) {
74
74
  let result = "unknown";
75
75
  for (const [left, right] of [[own, peer], [peer, own]]) {
76
76
  options.signal?.throwIfAborted();
77
- const authority = authorities.get(left.filesystem);
77
+ const authority = authorities.get(left.filesystem) ?? left.filesystem._entryAuthority;
78
78
  const key = authority ?? left.filesystem;
79
79
  if (queried.has(key))
80
80
  continue;
@@ -9,7 +9,8 @@ export function withObjectFileDescriptors(filesystem, store, options = {}) {
9
9
  const maxStagedPages = options.maxStagedPages ?? Infinity;
10
10
  const maxFileBytes = options.maxFileBytes ?? Infinity;
11
11
  const maxOpenFiles = options.maxOpenFiles ?? Infinity;
12
- if (![chunkBytes, options.maxStagedBytes, options.maxStagedPages, options.maxFileBytes, options.maxOpenFiles].every(value => value === undefined || Number.isSafeInteger(value) && value > 0)
12
+ if (!Number.isSafeInteger(chunkBytes) || chunkBytes < 1
13
+ || ![maxStagedBytes, maxStagedPages, maxFileBytes, maxOpenFiles].every(value => value === Infinity || Number.isSafeInteger(value) && value > 0)
13
14
  || typeof store.acquire !== "function"
14
15
  || store.publish !== undefined && typeof store.publish !== "function"
15
16
  || store.createStaging !== undefined && typeof store.createStaging !== "function")
@@ -202,7 +202,7 @@ export class ReadOnlyFileSystem {
202
202
  readOnly("openResizeFile", path);
203
203
  }
204
204
  }
205
- const readOnlyImplementation = Object.getOwnPropertyDescriptors(ReadOnlyFileSystem.prototype);
205
+ const readOnlyImplementation = /* @__PURE__ */ Object.getOwnPropertyDescriptors(ReadOnlyFileSystem.prototype);
206
206
  export function createReadOnlyFileSystem(filesystem) {
207
207
  return new ReadOnlyFileSystem(filesystem);
208
208
  }
@@ -608,8 +608,9 @@ export class RealFileSystem {
608
608
  }
609
609
  async readFile(path, options = {}) {
610
610
  return this.operation("readFile", path, options, async () => {
611
- const maxBytes = options.maxBytes ?? Number.MAX_SAFE_INTEGER;
612
- integer(maxBytes);
611
+ const maxBytes = options.maxBytes ?? Infinity;
612
+ if (maxBytes !== Infinity)
613
+ integer(maxBytes);
613
614
  return collectBytes(this.readStream(path, options), { maxBytes, ...options });
614
615
  });
615
616
  }
@@ -1134,4 +1134,4 @@ export class S3FileSystem {
1134
1134
  }
1135
1135
  }
1136
1136
  }
1137
- const s3Comparison = S3FileSystem.prototype.compareEntry;
1137
+ const s3Comparison = /* @__PURE__ */ (() => S3FileSystem.prototype.compareEntry)();
@@ -1,4 +1,15 @@
1
- import type { RequestOptions } from "node:http";
2
1
  import type { RequestScope, WireResponse } from "./request.js";
3
- import type { S3HttpRequestFactory } from "./types.js";
4
- export declare function sendRequest(options: RequestOptions, body: Uint8Array, scope: RequestScope, factory?: S3HttpRequestFactory): Promise<WireResponse>;
2
+ export type S3HttpRequestFactory = never;
3
+ interface FetchRequestOptions {
4
+ readonly protocol?: string | undefined;
5
+ readonly hostname?: string | undefined;
6
+ readonly port?: string | number | undefined;
7
+ readonly path?: string | undefined;
8
+ readonly method?: string | undefined;
9
+ readonly headers?: Record<string, string> | undefined;
10
+ readonly agent?: false;
11
+ readonly maxHeaderSize?: number;
12
+ readonly rejectUnauthorized?: true;
13
+ }
14
+ export declare function sendRequest(options: FetchRequestOptions, body: Uint8Array, scope: RequestScope, factory?: S3HttpRequestFactory): Promise<WireResponse>;
15
+ export {};