@zenfs/core 1.2.4 → 1.2.5

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.
@@ -7,4 +7,8 @@ export declare const config: {
7
7
  * Whether to sync atime updates immediately when reading from a file
8
8
  */
9
9
  updateOnRead: boolean;
10
+ /**
11
+ * If a file's buffer is not large enough to store content when writing and the buffer can't be resized, reuse the buffer passed to write()
12
+ */
13
+ unsafeBufferReplace: boolean;
10
14
  };
@@ -7,4 +7,8 @@ export const config = {
7
7
  * Whether to sync atime updates immediately when reading from a file
8
8
  */
9
9
  updateOnRead: true,
10
+ /**
11
+ * If a file's buffer is not large enough to store content when writing and the buffer can't be resized, reuse the buffer passed to write()
12
+ */
13
+ unsafeBufferReplace: false,
10
14
  };
@@ -485,7 +485,6 @@ async function _open(path, _flag, _mode = 0o644, resolveSymlinks) {
485
485
  */
486
486
  if (isTruncating(flag)) {
487
487
  await handle.truncate(0);
488
- await handle.sync();
489
488
  }
490
489
  return handle;
491
490
  }
@@ -738,24 +737,17 @@ link;
738
737
  * @param type can be either `'dir'` or `'file'` (default is `'file'`)
739
738
  */
740
739
  export async function symlink(target, path, type = 'file') {
741
- if (!['file', 'dir', 'junction'].includes(type)) {
742
- throw new ErrnoError(Errno.EINVAL, 'Invalid symlink type: ' + type);
743
- }
744
- if (await exists(path)) {
745
- throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
746
- }
747
- await writeFile(path, target.toString());
748
- const handle = await _open(path, 'r+', 0o644, false);
749
- await handle.file._setType(constants.S_IFLNK);
750
- }
751
- symlink;
752
- export async function readlink(path, options) {
753
740
  const env_5 = { stack: [], error: void 0, hasError: false };
754
741
  try {
755
- const handle = __addDisposableResource(env_5, await _open(normalizePath(path), 'r', 0o644, false), true);
756
- const value = await handle.readFile();
757
- const encoding = typeof options == 'object' ? options?.encoding : options;
758
- return encoding == 'buffer' ? value : value.toString(encoding);
742
+ if (!['file', 'dir', 'junction'].includes(type)) {
743
+ throw new ErrnoError(Errno.EINVAL, 'Invalid symlink type: ' + type);
744
+ }
745
+ if (await exists(path)) {
746
+ throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
747
+ }
748
+ const handle = __addDisposableResource(env_5, await _open(path, 'w+', 0o644, false), true);
749
+ await handle.writeFile(target.toString());
750
+ await handle.file._setType(constants.S_IFLNK);
759
751
  }
760
752
  catch (e_5) {
761
753
  env_5.error = e_5;
@@ -767,13 +759,14 @@ export async function readlink(path, options) {
767
759
  await result_5;
768
760
  }
769
761
  }
770
- readlink;
771
- // PROPERTY OPERATIONS
772
- export async function chown(path, uid, gid) {
762
+ symlink;
763
+ export async function readlink(path, options) {
773
764
  const env_6 = { stack: [], error: void 0, hasError: false };
774
765
  try {
775
- const handle = __addDisposableResource(env_6, await open(path, 'r+'), true);
776
- await handle.chown(uid, gid);
766
+ const handle = __addDisposableResource(env_6, await _open(normalizePath(path), 'r', 0o644, false), true);
767
+ const value = await handle.readFile();
768
+ const encoding = typeof options == 'object' ? options?.encoding : options;
769
+ return encoding == 'buffer' ? value : value.toString(encoding);
777
770
  }
778
771
  catch (e_6) {
779
772
  env_6.error = e_6;
@@ -785,11 +778,12 @@ export async function chown(path, uid, gid) {
785
778
  await result_6;
786
779
  }
787
780
  }
788
- chown;
789
- export async function lchown(path, uid, gid) {
781
+ readlink;
782
+ // PROPERTY OPERATIONS
783
+ export async function chown(path, uid, gid) {
790
784
  const env_7 = { stack: [], error: void 0, hasError: false };
791
785
  try {
792
- const handle = __addDisposableResource(env_7, await _open(path, 'r+', 0o644, false), true);
786
+ const handle = __addDisposableResource(env_7, await open(path, 'r+'), true);
793
787
  await handle.chown(uid, gid);
794
788
  }
795
789
  catch (e_7) {
@@ -802,12 +796,12 @@ export async function lchown(path, uid, gid) {
802
796
  await result_7;
803
797
  }
804
798
  }
805
- lchown;
806
- export async function chmod(path, mode) {
799
+ chown;
800
+ export async function lchown(path, uid, gid) {
807
801
  const env_8 = { stack: [], error: void 0, hasError: false };
808
802
  try {
809
- const handle = __addDisposableResource(env_8, await open(path, 'r+'), true);
810
- await handle.chmod(mode);
803
+ const handle = __addDisposableResource(env_8, await _open(path, 'r+', 0o644, false), true);
804
+ await handle.chown(uid, gid);
811
805
  }
812
806
  catch (e_8) {
813
807
  env_8.error = e_8;
@@ -819,11 +813,11 @@ export async function chmod(path, mode) {
819
813
  await result_8;
820
814
  }
821
815
  }
822
- chmod;
823
- export async function lchmod(path, mode) {
816
+ lchown;
817
+ export async function chmod(path, mode) {
824
818
  const env_9 = { stack: [], error: void 0, hasError: false };
825
819
  try {
826
- const handle = __addDisposableResource(env_9, await _open(path, 'r+', 0o644, false), true);
820
+ const handle = __addDisposableResource(env_9, await open(path, 'r+'), true);
827
821
  await handle.chmod(mode);
828
822
  }
829
823
  catch (e_9) {
@@ -836,15 +830,12 @@ export async function lchmod(path, mode) {
836
830
  await result_9;
837
831
  }
838
832
  }
839
- lchmod;
840
- /**
841
- * Change file timestamps of the file referenced by the supplied path.
842
- */
843
- export async function utimes(path, atime, mtime) {
833
+ chmod;
834
+ export async function lchmod(path, mode) {
844
835
  const env_10 = { stack: [], error: void 0, hasError: false };
845
836
  try {
846
- const handle = __addDisposableResource(env_10, await open(path, 'r+'), true);
847
- await handle.utimes(atime, mtime);
837
+ const handle = __addDisposableResource(env_10, await _open(path, 'r+', 0o644, false), true);
838
+ await handle.chmod(mode);
848
839
  }
849
840
  catch (e_10) {
850
841
  env_10.error = e_10;
@@ -856,15 +847,15 @@ export async function utimes(path, atime, mtime) {
856
847
  await result_10;
857
848
  }
858
849
  }
859
- utimes;
850
+ lchmod;
860
851
  /**
861
852
  * Change file timestamps of the file referenced by the supplied path.
862
853
  */
863
- export async function lutimes(path, atime, mtime) {
854
+ export async function utimes(path, atime, mtime) {
864
855
  const env_11 = { stack: [], error: void 0, hasError: false };
865
856
  try {
866
- const handle = __addDisposableResource(env_11, await _open(path, 'r+', 0o644, false), true);
867
- await handle.utimes(new Date(atime), new Date(mtime));
857
+ const handle = __addDisposableResource(env_11, await open(path, 'r+'), true);
858
+ await handle.utimes(atime, mtime);
868
859
  }
869
860
  catch (e_11) {
870
861
  env_11.error = e_11;
@@ -876,6 +867,26 @@ export async function lutimes(path, atime, mtime) {
876
867
  await result_11;
877
868
  }
878
869
  }
870
+ utimes;
871
+ /**
872
+ * Change file timestamps of the file referenced by the supplied path.
873
+ */
874
+ export async function lutimes(path, atime, mtime) {
875
+ const env_12 = { stack: [], error: void 0, hasError: false };
876
+ try {
877
+ const handle = __addDisposableResource(env_12, await _open(path, 'r+', 0o644, false), true);
878
+ await handle.utimes(new Date(atime), new Date(mtime));
879
+ }
880
+ catch (e_12) {
881
+ env_12.error = e_12;
882
+ env_12.hasError = true;
883
+ }
884
+ finally {
885
+ const result_12 = __disposeResources(env_12);
886
+ if (result_12)
887
+ await result_12;
888
+ }
889
+ }
879
890
  lutimes;
880
891
  export async function realpath(path, options) {
881
892
  path = normalizePath(path);
@@ -193,7 +193,6 @@ function _openSync(path, _flag, _mode, resolveSymlinks = true) {
193
193
  const file = fs.openFileSync(resolved, flag);
194
194
  if (isTruncating(flag)) {
195
195
  file.truncateSync(0);
196
- file.syncSync();
197
196
  }
198
197
  return file;
199
198
  }
package/dist/file.js CHANGED
@@ -299,17 +299,21 @@ export class PreloadFile extends File {
299
299
  if (this.closed) {
300
300
  throw ErrnoError.With('EBADF', this.path, 'File.write');
301
301
  }
302
- this.dirty = true;
303
302
  if (!isWriteable(this.flag)) {
304
303
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
305
304
  }
305
+ this.dirty = true;
306
306
  const end = position + length;
307
+ const slice = buffer.slice(offset, offset + length);
307
308
  if (end > this.stats.size) {
308
309
  this.stats.size = end;
309
310
  if (end > this._buffer.byteLength) {
310
311
  if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= end) {
311
312
  this._buffer.buffer.resize(end);
312
313
  }
314
+ else if (config.unsafeBufferReplace) {
315
+ this._buffer = slice;
316
+ }
313
317
  else {
314
318
  // Extend the buffer!
315
319
  const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
@@ -318,7 +322,6 @@ export class PreloadFile extends File {
318
322
  }
319
323
  }
320
324
  }
321
- const slice = buffer.slice(offset, offset + length);
322
325
  this._buffer.set(slice, position);
323
326
  this.stats.mtimeMs = Date.now();
324
327
  this.position = position + slice.byteLength;
@@ -370,7 +373,7 @@ export class PreloadFile extends File {
370
373
  this._position = end;
371
374
  const bytesRead = end - position;
372
375
  if (bytesRead == 0) {
373
- // No copy/read. Return immediatly for better performance
376
+ // No copy/read. Return immediately for better performance
374
377
  return bytesRead;
375
378
  }
376
379
  new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "A filesystem, anywhere",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -8,4 +8,9 @@ export const config = {
8
8
  * Whether to sync atime updates immediately when reading from a file
9
9
  */
10
10
  updateOnRead: true,
11
+
12
+ /**
13
+ * If a file's buffer is not large enough to store content when writing and the buffer can't be resized, reuse the buffer passed to write()
14
+ */
15
+ unsafeBufferReplace: false,
11
16
  };
@@ -529,7 +529,6 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
529
529
  */
530
530
  if (isTruncating(flag)) {
531
531
  await handle.truncate(0);
532
- await handle.sync();
533
532
  }
534
533
 
535
534
  return handle;
@@ -832,8 +831,8 @@ export async function symlink(target: fs.PathLike, path: fs.PathLike, type: fs.s
832
831
  throw ErrnoError.With('EEXIST', path.toString(), 'symlink');
833
832
  }
834
833
 
835
- await writeFile(path, target.toString());
836
- const handle = await _open(path, 'r+', 0o644, false);
834
+ await using handle = await _open(path, 'w+', 0o644, false);
835
+ await handle.writeFile(target.toString());
837
836
  await handle.file._setType(constants.S_IFLNK);
838
837
  }
839
838
  symlink satisfies typeof promises.symlink;
@@ -159,7 +159,6 @@ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null
159
159
 
160
160
  if (isTruncating(flag)) {
161
161
  file.truncateSync(0);
162
- file.syncSync();
163
162
  }
164
163
 
165
164
  return file;
package/src/file.ts CHANGED
@@ -453,17 +453,22 @@ export class PreloadFile<FS extends FileSystem> extends File {
453
453
  if (this.closed) {
454
454
  throw ErrnoError.With('EBADF', this.path, 'File.write');
455
455
  }
456
- this.dirty = true;
456
+
457
457
  if (!isWriteable(this.flag)) {
458
458
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
459
459
  }
460
+
461
+ this.dirty = true;
460
462
  const end = position + length;
463
+ const slice = buffer.slice(offset, offset + length);
461
464
 
462
465
  if (end > this.stats.size) {
463
466
  this.stats.size = end;
464
467
  if (end > this._buffer.byteLength) {
465
468
  if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength! <= end) {
466
469
  this._buffer.buffer.resize(end);
470
+ } else if (config.unsafeBufferReplace) {
471
+ this._buffer = slice;
467
472
  } else {
468
473
  // Extend the buffer!
469
474
  const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
@@ -472,7 +477,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
472
477
  }
473
478
  }
474
479
  }
475
- const slice = buffer.slice(offset, offset + length);
480
+
476
481
  this._buffer.set(slice, position);
477
482
  this.stats.mtimeMs = Date.now();
478
483
  this.position = position + slice.byteLength;
@@ -527,7 +532,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
527
532
  this._position = end;
528
533
  const bytesRead = end - position;
529
534
  if (bytesRead == 0) {
530
- // No copy/read. Return immediatly for better performance
535
+ // No copy/read. Return immediately for better performance
531
536
  return bytesRead;
532
537
  }
533
538
  new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
@@ -4,45 +4,41 @@ import { fs } from '../common.js';
4
4
 
5
5
  const asyncMode = 0o777;
6
6
  const syncMode = 0o644;
7
+ const file = 'a.js';
7
8
 
8
9
  suite('chmod tests', () => {
9
10
  test('chmod', async () => {
10
- const file1 = 'a.js';
11
+ await fs.promises.chmod(file, asyncMode.toString(8));
11
12
 
12
- await fs.promises.chmod(file1, asyncMode.toString(8));
13
+ const stats = await fs.promises.stat(file);
14
+ assert.equal(stats.mode & 0o777, asyncMode);
13
15
 
14
- const stats = await fs.promises.stat(file1);
15
- assert((stats.mode & 0o777) === asyncMode);
16
-
17
- fs.chmodSync(file1, syncMode);
18
- assert((fs.statSync(file1).mode & 0o777) === syncMode);
16
+ fs.chmodSync(file, syncMode);
17
+ assert.equal(fs.statSync(file).mode & 0o777, syncMode);
19
18
  });
20
19
 
21
20
  test('fchmod', async () => {
22
- const file2 = 'a1.js';
23
-
24
- const handle = await fs.promises.open(file2, 'a', 0o644);
21
+ const handle = await fs.promises.open(file, 'a', 0o644);
25
22
 
26
23
  await handle.chmod(asyncMode);
27
24
  const stats = await handle.stat();
28
25
 
29
- assert((stats.mode & 0o777) === asyncMode);
26
+ assert.equal(stats.mode & 0o777, asyncMode);
30
27
 
31
28
  fs.fchmodSync(handle.fd, syncMode);
32
- assert((fs.statSync(file2).mode & 0o777) === syncMode);
29
+ assert.equal(fs.statSync(file).mode & 0o777, syncMode);
33
30
  });
34
31
 
35
32
  test('lchmod', async () => {
36
33
  const link = 'symbolic-link';
37
- const target = 'a1.js';
38
34
 
39
- await fs.promises.symlink(target, link);
35
+ await fs.promises.symlink(file, link);
40
36
  await fs.promises.lchmod(link, asyncMode);
41
37
 
42
38
  const stats = await fs.promises.lstat(link);
43
- assert((stats.mode & 0o777) === asyncMode);
39
+ assert.equal(stats.mode & 0o777, asyncMode);
44
40
 
45
41
  fs.lchmodSync(link, syncMode);
46
- assert((fs.lstatSync(link).mode & 0o777) === syncMode);
42
+ assert.equal(fs.lstatSync(link).mode & 0o777, syncMode);
47
43
  });
48
44
  });
@@ -10,22 +10,22 @@ const path: string = 'truncate-file.txt',
10
10
  suite('Truncate, sync', () => {
11
11
  test('initial write', () => {
12
12
  fs.writeFileSync(path, data);
13
- assert(fs.statSync(path).size === size);
13
+ assert.equal(fs.statSync(path).size, size);
14
14
  });
15
15
 
16
16
  test('truncate to 1024', () => {
17
17
  fs.truncateSync(path, 1024);
18
- assert(fs.statSync(path).size === 1024);
18
+ assert.equal(fs.statSync(path).size, 1024);
19
19
  });
20
20
 
21
21
  test('truncate to 0', () => {
22
22
  fs.truncateSync(path);
23
- assert(fs.statSync(path).size === 0);
23
+ assert.equal(fs.statSync(path).size, 0);
24
24
  });
25
25
 
26
26
  test('write', () => {
27
27
  fs.writeFileSync(path, data);
28
- assert(fs.statSync(path).size === size);
28
+ assert.equal(fs.statSync(path).size, size);
29
29
  });
30
30
 
31
31
  let fd: number;
@@ -35,12 +35,12 @@ suite('Truncate, sync', () => {
35
35
 
36
36
  test('ftruncate to 1024', () => {
37
37
  fs.ftruncateSync(fd, 1024);
38
- assert(fs.fstatSync(fd).size === 1024);
38
+ assert.equal(fs.fstatSync(fd).size, 1024);
39
39
  });
40
40
 
41
41
  test('ftruncate to 0', () => {
42
42
  fs.ftruncateSync(fd);
43
- assert(fs.fstatSync(fd).size === 0);
43
+ assert.equal(fs.fstatSync(fd).size, 0);
44
44
  });
45
45
 
46
46
  test('close fd', () => {
@@ -53,22 +53,22 @@ suite('Truncate, async', () => {
53
53
  test('initial write', async () => {
54
54
  await fs.promises.writeFile(path, data);
55
55
 
56
- assert((await statSize(path)) === 1024 * 16);
56
+ assert.equal(await statSize(path), 1024 * 16);
57
57
  });
58
58
 
59
59
  test('truncate to 1024', async () => {
60
60
  await fs.promises.truncate(path, 1024);
61
- assert((await statSize(path)) === 1024);
61
+ assert.equal(await statSize(path), 1024);
62
62
  });
63
63
 
64
64
  test('truncate to 0', async () => {
65
65
  await fs.promises.truncate(path);
66
- assert((await statSize(path)) === 0);
66
+ assert.equal(await statSize(path), 0);
67
67
  });
68
68
 
69
69
  test('write', async () => {
70
70
  await fs.promises.writeFile(path, data);
71
- assert((await statSize(path)) === size);
71
+ assert.equal(await statSize(path), size);
72
72
  });
73
73
 
74
74
  let handle: FileHandle;
@@ -79,13 +79,13 @@ suite('Truncate, async', () => {
79
79
  test('handle.truncate to 1024', async () => {
80
80
  await handle.truncate(1024);
81
81
  await handle.sync();
82
- assert((await statSize(path)) === 1024);
82
+ assert.equal(await statSize(path), 1024);
83
83
  });
84
84
 
85
85
  test('handle.truncate to 0', async () => {
86
86
  await handle.truncate();
87
87
  await handle.sync();
88
- assert((await statSize(path)) === 0);
88
+ assert.equal(await statSize(path), 0);
89
89
  });
90
90
 
91
91
  test('close handle', async () => {