@zenfs/core 0.18.0 → 1.0.0-rc.0

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.
@@ -10,3 +10,4 @@ export type Mixin<TBase extends typeof FileSystem, TMixin> = (abstract new (...a
10
10
  * @internal
11
11
  */
12
12
  export type _AsyncFSMethods = ExtractProperties<FileSystem, (...args: any[]) => Promise<unknown>>;
13
+ export type ConcreteFS = ExtractProperties<FileSystem, any>;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  /*
2
3
  Code shared by various mixins
3
4
  */
package/dist/stats.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type * as Node from 'fs';
3
- import type { Credentials } from './credentials.js';
3
+ import { type Credentials } from './credentials.js';
4
4
  import { S_IFDIR, S_IFLNK, S_IFREG } from './emulation/constants.js';
5
5
  /**
6
6
  * Indicates the type of the given file. Applied to 'mode'.
@@ -146,11 +146,10 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
146
146
  /**
147
147
  * Checks if a given user/group has access to this item
148
148
  * @param mode The requested access, combination of W_OK, R_OK, and X_OK
149
- * @param cred The requesting credentials
150
149
  * @returns True if the request has access, false if the request does not
151
150
  * @internal
152
151
  */
153
- hasAccess(mode: number, cred: Credentials): boolean;
152
+ hasAccess(mode: number): boolean;
154
153
  /**
155
154
  * Convert the current stats object into a credentials object
156
155
  * @internal
package/dist/stats.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { credentials } from './credentials.js';
1
2
  import { S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK, S_IRWXG, S_IRWXO, S_IRWXU } from './emulation/constants.js';
2
3
  import { size_max } from './inode.js';
3
4
  /**
@@ -115,17 +116,16 @@ export class StatsCommon {
115
116
  /**
116
117
  * Checks if a given user/group has access to this item
117
118
  * @param mode The requested access, combination of W_OK, R_OK, and X_OK
118
- * @param cred The requesting credentials
119
119
  * @returns True if the request has access, false if the request does not
120
120
  * @internal
121
121
  */
122
- hasAccess(mode, cred) {
123
- if (cred.euid === 0 || cred.egid === 0) {
122
+ hasAccess(mode) {
123
+ if (credentials.euid === 0 || credentials.egid === 0) {
124
124
  //Running as root
125
125
  return true;
126
126
  }
127
127
  // Mask for
128
- const adjusted = (cred.uid == this.uid ? S_IRWXU : 0) | (cred.gid == this.gid ? S_IRWXG : 0) | S_IRWXO;
128
+ const adjusted = (credentials.uid == this.uid ? S_IRWXU : 0) | (credentials.gid == this.gid ? S_IRWXG : 0) | S_IRWXO;
129
129
  return (mode & this.mode & adjusted) == mode;
130
130
  }
131
131
  /**
package/dist/utils.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  /// <reference types="node" resolution-mode="require"/>
3
3
  import type * as fs from 'node:fs';
4
- import type { OptionalTuple } from 'utilium';
4
+ import type { ClassLike, OptionalTuple } from 'utilium';
5
5
  import { type AbsolutePath } from './emulation/path.js';
6
6
  import { ErrnoError } from './error.js';
7
7
  import type { FileSystem } from './filesystem.js';
@@ -81,3 +81,4 @@ export declare function normalizeOptions(options: fs.WriteFileOptions | (fs.Enco
81
81
  flag: string;
82
82
  mode: number;
83
83
  };
84
+ export type Concrete<T extends ClassLike> = Pick<T, keyof T> & (new (...args: any[]) => InstanceType<T>);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "0.18.0",
3
+ "version": "1.0.0-rc.0",
4
4
  "description": "A filesystem, anywhere",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/readme.md CHANGED
@@ -17,7 +17,7 @@ ZenFS is modular and extensible. The core includes some built-in backends:
17
17
 
18
18
  ZenFS supports a number of other backends. Many are provided as separate packages under `@zenfs`. More backends can be defined by separate libraries by extending the `FileSystem` class and providing a `Backend` object.
19
19
 
20
- As an added bonus, all ZenFS backends support syncrohnous operations. All of the backends included with the core are cross-platform.
20
+ As an added bonus, all ZenFS backends support synchronous operations. All of the backends included with the core are cross-platform.
21
21
 
22
22
  For more information, see the [docs](https://zen-fs.github.io/core).
23
23
 
@@ -432,31 +432,29 @@ export class UnmutexedOverlayFS extends FileSystem {
432
432
  * should they not exist. Use modes from the read-only storage.
433
433
  */
434
434
  private createParentDirectoriesSync(path: string): void {
435
- let parent = dirname(path),
436
- toCreate: string[] = [];
435
+ let parent = dirname(path);
436
+ const toCreate: string[] = [];
437
437
  while (!this.writable.existsSync(parent)) {
438
438
  toCreate.push(parent);
439
439
  parent = dirname(parent);
440
440
  }
441
- toCreate = toCreate.reverse();
442
441
 
443
- for (const p of toCreate) {
444
- this.writable.mkdirSync(p, this.statSync(p).mode);
442
+ for (const path of toCreate.reverse()) {
443
+ this.writable.mkdirSync(path, this.statSync(path).mode);
445
444
  }
446
445
  }
447
446
 
448
447
  private async createParentDirectories(path: string): Promise<void> {
449
- let parent = dirname(path),
450
- toCreate: string[] = [];
448
+ let parent = dirname(path);
449
+ const toCreate: string[] = [];
451
450
  while (!(await this.writable.exists(parent))) {
452
451
  toCreate.push(parent);
453
452
  parent = dirname(parent);
454
453
  }
455
- toCreate = toCreate.reverse();
456
454
 
457
- for (const p of toCreate) {
458
- const stats = await this.stat(p);
459
- await this.writable.mkdir(p, stats.mode);
455
+ for (const path of toCreate.reverse()) {
456
+ const stats = await this.stat(path);
457
+ await this.writable.mkdir(path, stats.mode);
460
458
  }
461
459
  }
462
460
 
@@ -22,12 +22,12 @@ interface FileRequest<TMethod extends FileMethod = FileMethod> extends RPC.Reque
22
22
 
23
23
  export class PortFile extends File {
24
24
  constructor(
25
- public readonly fs: PortFS,
25
+ public fs: PortFS,
26
26
  public readonly fd: number,
27
- public readonly path: string,
27
+ path: string,
28
28
  public position: number
29
29
  ) {
30
- super();
30
+ super(fs, path);
31
31
  }
32
32
 
33
33
  public rpc<const T extends FileMethod>(method: T, ...args: Parameters<FileMethods[T]>): Promise<Awaited<ReturnType<FileMethods[T]>>> {
@@ -43,7 +43,7 @@ export class PortFile extends File {
43
43
  }
44
44
 
45
45
  protected _throwNoSync(syscall: string): never {
46
- throw new ErrnoError(Errno.ENOTSUP, 'Syncrohnous operations not support on PortFile', this.path, syscall);
46
+ throw new ErrnoError(Errno.ENOTSUP, 'Synchronous operations not supported on PortFile', this.path, syscall);
47
47
  }
48
48
 
49
49
  public async stat(): Promise<Stats> {
@@ -18,7 +18,6 @@ import * as constants from './constants.js';
18
18
  import { Dir, Dirent } from './dir.js';
19
19
  import { dirname, join, parse } from './path.js';
20
20
  import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
21
- import { credentials } from '../credentials.js';
22
21
  import { ReadStream, WriteStream } from './streams.js';
23
22
  import { FSWatcher, emitChange } from './watchers.js';
24
23
  export * as constants from './constants.js';
@@ -220,7 +219,7 @@ export class FileHandle implements promises.FileHandle {
220
219
  public async stat(opts?: fs.StatOptions & { bigint?: false }): Promise<Stats>;
221
220
  public async stat(opts?: fs.StatOptions): Promise<Stats | BigIntStats> {
222
221
  const stats = await this.file.stat();
223
- if (!stats.hasAccess(constants.R_OK, credentials)) {
222
+ if (!stats.hasAccess(constants.R_OK)) {
224
223
  throw ErrnoError.With('EACCES', this.file.path, 'stat');
225
224
  }
226
225
  return opts?.bigint ? new BigIntStats(stats) : stats;
@@ -396,7 +395,7 @@ export async function rename(oldPath: fs.PathLike, newPath: fs.PathLike): Promis
396
395
  newPath = normalizePath(newPath);
397
396
  const src = resolveMount(oldPath);
398
397
  const dst = resolveMount(newPath);
399
- if (!(await stat(dirname(oldPath))).hasAccess(constants.W_OK, credentials)) {
398
+ if (!(await stat(dirname(oldPath))).hasAccess(constants.W_OK)) {
400
399
  throw ErrnoError.With('EACCES', oldPath, 'rename');
401
400
  }
402
401
  try {
@@ -444,7 +443,7 @@ export async function stat(path: fs.PathLike, options?: fs.StatOptions): Promise
444
443
  const { fs, path: resolved } = resolveMount((await exists(path)) ? await realpath(path) : path);
445
444
  try {
446
445
  const stats = await fs.stat(resolved);
447
- if (!stats.hasAccess(constants.R_OK, credentials)) {
446
+ if (!stats.hasAccess(constants.R_OK)) {
448
447
  throw ErrnoError.With('EACCES', path, 'stat');
449
448
  }
450
449
  return options?.bigint ? new BigIntStats(stats) : stats;
@@ -496,7 +495,7 @@ export async function unlink(path: fs.PathLike): Promise<void> {
496
495
  path = normalizePath(path);
497
496
  const { fs, path: resolved } = resolveMount(path);
498
497
  try {
499
- if (!(await fs.stat(resolved)).hasAccess(constants.W_OK, credentials)) {
498
+ if (!(await fs.stat(resolved)).hasAccess(constants.W_OK)) {
500
499
  throw ErrnoError.With('EACCES', resolved, 'unlink');
501
500
  }
502
501
  await fs.unlink(resolved);
@@ -527,7 +526,7 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
527
526
  }
528
527
  // Create the file
529
528
  const parentStats: Stats = await fs.stat(dirname(resolved));
530
- if (!parentStats.hasAccess(constants.W_OK, credentials)) {
529
+ if (!parentStats.hasAccess(constants.W_OK)) {
531
530
  throw ErrnoError.With('EACCES', dirname(path), '_open');
532
531
  }
533
532
  if (!parentStats.isDirectory()) {
@@ -536,7 +535,7 @@ async function _open(path: fs.PathLike, _flag: fs.OpenMode, _mode: fs.Mode = 0o6
536
535
  return new FileHandle(await fs.createFile(resolved, flag, mode));
537
536
  }
538
537
 
539
- if (!stats.hasAccess(flagToMode(flag), credentials)) {
538
+ if (!stats.hasAccess(flagToMode(flag))) {
540
539
  throw ErrnoError.With('EACCES', path, '_open');
541
540
  }
542
541
 
@@ -663,7 +662,7 @@ export async function rmdir(path: fs.PathLike): Promise<void> {
663
662
  path = (await exists(path)) ? await realpath(path) : path;
664
663
  const { fs, path: resolved } = resolveMount(path);
665
664
  try {
666
- if (!(await fs.stat(resolved)).hasAccess(constants.W_OK, credentials)) {
665
+ if (!(await fs.stat(resolved)).hasAccess(constants.W_OK)) {
667
666
  throw ErrnoError.With('EACCES', resolved, 'rmdir');
668
667
  }
669
668
  await fs.rmdir(resolved);
@@ -694,7 +693,7 @@ export async function mkdir(path: fs.PathLike, options?: fs.Mode | fs.MakeDirect
694
693
 
695
694
  try {
696
695
  if (!options?.recursive) {
697
- if (!(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK, credentials)) {
696
+ if (!(await fs.stat(dirname(resolved))).hasAccess(constants.W_OK)) {
698
697
  throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
699
698
  }
700
699
  await fs.mkdir(resolved, mode);
@@ -708,7 +707,7 @@ export async function mkdir(path: fs.PathLike, options?: fs.Mode | fs.MakeDirect
708
707
  errorPaths[dir] = origDir;
709
708
  }
710
709
  for (const dir of dirs) {
711
- if (!(await fs.stat(dirname(dir))).hasAccess(constants.W_OK, credentials)) {
710
+ if (!(await fs.stat(dirname(dir))).hasAccess(constants.W_OK)) {
712
711
  throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
713
712
  }
714
713
  await fs.mkdir(dir, mode);
@@ -738,7 +737,7 @@ export async function readdir(
738
737
  options?: { withFileTypes?: boolean; recursive?: boolean; encoding?: BufferEncoding | 'buffer' | null } | BufferEncoding | 'buffer' | null
739
738
  ): Promise<string[] | Dirent[] | Buffer[]> {
740
739
  path = normalizePath(path);
741
- if (!(await stat(path)).hasAccess(constants.R_OK, credentials)) {
740
+ if (!(await stat(path)).hasAccess(constants.R_OK)) {
742
741
  throw ErrnoError.With('EACCES', path, 'readdir');
743
742
  }
744
743
  path = (await exists(path)) ? await realpath(path) : path;
@@ -776,11 +775,11 @@ readdir satisfies typeof promises.readdir;
776
775
  */
777
776
  export async function link(targetPath: fs.PathLike, linkPath: fs.PathLike): Promise<void> {
778
777
  targetPath = normalizePath(targetPath);
779
- if (!(await stat(dirname(targetPath))).hasAccess(constants.R_OK, credentials)) {
778
+ if (!(await stat(dirname(targetPath))).hasAccess(constants.R_OK)) {
780
779
  throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
781
780
  }
782
781
  linkPath = normalizePath(linkPath);
783
- if (!(await stat(dirname(linkPath))).hasAccess(constants.W_OK, credentials)) {
782
+ if (!(await stat(dirname(linkPath))).hasAccess(constants.W_OK)) {
784
783
  throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
785
784
  }
786
785
 
@@ -790,7 +789,7 @@ export async function link(targetPath: fs.PathLike, linkPath: fs.PathLike): Prom
790
789
  throw ErrnoError.With('EXDEV', linkPath, 'link');
791
790
  }
792
791
  try {
793
- if (!(await fs.stat(path)).hasAccess(constants.W_OK, credentials)) {
792
+ if (!(await fs.stat(path)).hasAccess(constants.W_OK)) {
794
793
  throw ErrnoError.With('EACCES', path, 'link');
795
794
  }
796
795
  return await fs.link(path, link.path);
@@ -969,7 +968,7 @@ watch satisfies typeof promises.watch;
969
968
  */
970
969
  export async function access(path: fs.PathLike, mode: number = constants.F_OK): Promise<void> {
971
970
  const stats = await stat(path);
972
- if (!stats.hasAccess(mode, credentials)) {
971
+ if (!stats.hasAccess(mode)) {
973
972
  throw new ErrnoError(Errno.EACCES);
974
973
  }
975
974
  }
@@ -10,7 +10,6 @@ import * as constants from './constants.js';
10
10
  import { Dir, Dirent } from './dir.js';
11
11
  import { dirname, join, parse } from './path.js';
12
12
  import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
13
- import { credentials } from '../credentials.js';
14
13
  import { emitChange } from './watchers.js';
15
14
 
16
15
  /**
@@ -23,7 +22,7 @@ export function renameSync(oldPath: fs.PathLike, newPath: fs.PathLike): void {
23
22
  newPath = normalizePath(newPath);
24
23
  const oldMount = resolveMount(oldPath);
25
24
  const newMount = resolveMount(newPath);
26
- if (!statSync(dirname(oldPath)).hasAccess(constants.W_OK, credentials)) {
25
+ if (!statSync(dirname(oldPath)).hasAccess(constants.W_OK)) {
27
26
  throw ErrnoError.With('EACCES', oldPath, 'rename');
28
27
  }
29
28
  try {
@@ -73,7 +72,7 @@ export function statSync(path: fs.PathLike, options?: fs.StatOptions): Stats | B
73
72
  const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
74
73
  try {
75
74
  const stats = fs.statSync(resolved);
76
- if (!stats.hasAccess(constants.R_OK, credentials)) {
75
+ if (!stats.hasAccess(constants.R_OK)) {
77
76
  throw ErrnoError.With('EACCES', path, 'stat');
78
77
  }
79
78
  return options?.bigint ? new BigIntStats(stats) : stats;
@@ -126,7 +125,7 @@ export function unlinkSync(path: fs.PathLike): void {
126
125
  path = normalizePath(path);
127
126
  const { fs, path: resolved } = resolveMount(path);
128
127
  try {
129
- if (!fs.statSync(resolved).hasAccess(constants.W_OK, credentials)) {
128
+ if (!fs.statSync(resolved).hasAccess(constants.W_OK)) {
130
129
  throw ErrnoError.With('EACCES', resolved, 'unlink');
131
130
  }
132
131
  fs.unlinkSync(resolved);
@@ -151,7 +150,7 @@ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null
151
150
  }
152
151
  // Create the file
153
152
  const parentStats: Stats = fs.statSync(dirname(resolved));
154
- if (!parentStats.hasAccess(constants.W_OK, credentials)) {
153
+ if (!parentStats.hasAccess(constants.W_OK)) {
155
154
  throw ErrnoError.With('EACCES', dirname(path), '_open');
156
155
  }
157
156
  if (!parentStats.isDirectory()) {
@@ -162,7 +161,7 @@ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null
162
161
 
163
162
  const stats: Stats = fs.statSync(resolved);
164
163
 
165
- if (!stats.hasAccess(mode, credentials) || !stats.hasAccess(flagToMode(flag), credentials)) {
164
+ if (!stats.hasAccess(mode) || !stats.hasAccess(flagToMode(flag))) {
166
165
  throw ErrnoError.With('EACCES', path, '_open');
167
166
  }
168
167
 
@@ -466,7 +465,7 @@ export function rmdirSync(path: fs.PathLike): void {
466
465
  path = normalizePath(path);
467
466
  const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
468
467
  try {
469
- if (!fs.statSync(resolved).hasAccess(constants.W_OK, credentials)) {
468
+ if (!fs.statSync(resolved).hasAccess(constants.W_OK)) {
470
469
  throw ErrnoError.With('EACCES', resolved, 'rmdir');
471
470
  }
472
471
  fs.rmdirSync(resolved);
@@ -496,7 +495,7 @@ export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirector
496
495
 
497
496
  try {
498
497
  if (!options?.recursive) {
499
- if (!fs.statSync(dirname(resolved)).hasAccess(constants.W_OK, credentials)) {
498
+ if (!fs.statSync(dirname(resolved)).hasAccess(constants.W_OK)) {
500
499
  throw ErrnoError.With('EACCES', dirname(resolved), 'mkdir');
501
500
  }
502
501
  return fs.mkdirSync(resolved, mode);
@@ -508,7 +507,7 @@ export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirector
508
507
  errorPaths[dir] = original;
509
508
  }
510
509
  for (const dir of dirs) {
511
- if (!fs.statSync(dirname(dir)).hasAccess(constants.W_OK, credentials)) {
510
+ if (!fs.statSync(dirname(dir)).hasAccess(constants.W_OK)) {
512
511
  throw ErrnoError.With('EACCES', dirname(dir), 'mkdir');
513
512
  }
514
513
  fs.mkdirSync(dir, mode);
@@ -536,7 +535,7 @@ export function readdirSync(
536
535
  path = normalizePath(path);
537
536
  const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
538
537
  let entries: string[];
539
- if (!statSync(path).hasAccess(constants.R_OK, credentials)) {
538
+ if (!statSync(path).hasAccess(constants.R_OK)) {
540
539
  throw ErrnoError.With('EACCES', path, 'readdir');
541
540
  }
542
541
  try {
@@ -578,11 +577,11 @@ readdirSync satisfies typeof fs.readdirSync;
578
577
  */
579
578
  export function linkSync(targetPath: fs.PathLike, linkPath: fs.PathLike): void {
580
579
  targetPath = normalizePath(targetPath);
581
- if (!statSync(dirname(targetPath)).hasAccess(constants.R_OK, credentials)) {
580
+ if (!statSync(dirname(targetPath)).hasAccess(constants.R_OK)) {
582
581
  throw ErrnoError.With('EACCES', dirname(targetPath), 'link');
583
582
  }
584
583
  linkPath = normalizePath(linkPath);
585
- if (!statSync(dirname(linkPath)).hasAccess(constants.W_OK, credentials)) {
584
+ if (!statSync(dirname(linkPath)).hasAccess(constants.W_OK)) {
586
585
  throw ErrnoError.With('EACCES', dirname(linkPath), 'link');
587
586
  }
588
587
 
@@ -592,7 +591,7 @@ export function linkSync(targetPath: fs.PathLike, linkPath: fs.PathLike): void {
592
591
  throw ErrnoError.With('EXDEV', linkPath, 'link');
593
592
  }
594
593
  try {
595
- if (!fs.statSync(path).hasAccess(constants.W_OK, credentials)) {
594
+ if (!fs.statSync(path).hasAccess(constants.W_OK)) {
596
595
  throw ErrnoError.With('EACCES', path, 'link');
597
596
  }
598
597
  return fs.linkSync(path, linkPath);
@@ -753,7 +752,7 @@ realpathSync satisfies Omit<typeof fs.realpathSync, 'native'>;
753
752
  */
754
753
  export function accessSync(path: fs.PathLike, mode: number = 0o600): void {
755
754
  const stats = statSync(path);
756
- if (!stats.hasAccess(mode, credentials)) {
755
+ if (!stats.hasAccess(mode)) {
757
756
  throw new ErrnoError(Errno.EACCES);
758
757
  }
759
758
  }
package/src/file.ts CHANGED
@@ -146,16 +146,23 @@ export function isExclusive(flag: string): boolean {
146
146
  }
147
147
 
148
148
  export abstract class File {
149
+ constructor(
150
+ /**
151
+ * @internal
152
+ * The file system that created the file
153
+ */
154
+ public fs: FileSystem,
155
+ /**
156
+ * The path to the file
157
+ */
158
+ public readonly path: string
159
+ ) {}
160
+
149
161
  /**
150
162
  * Get the current file position.
151
163
  */
152
164
  public abstract position: number;
153
165
 
154
- /**
155
- * The path to the file
156
- */
157
- public abstract readonly path: string;
158
-
159
166
  /**
160
167
  * Asynchronous `stat`.
161
168
  */
@@ -355,17 +362,15 @@ export class PreloadFile<FS extends FileSystem> extends File {
355
362
  constructor(
356
363
  /**
357
364
  * The file system that created the file.
365
+ * @internal
358
366
  */
359
- protected fs: FS,
360
- /**
361
- * Path to the file
362
- */
363
- public readonly path: string,
367
+ public fs: FS,
368
+ path: string,
364
369
  public readonly flag: string,
365
370
  public readonly stats: Stats,
366
371
  protected _buffer: Uint8Array = new Uint8Array(new ArrayBuffer(0, fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }))
367
372
  ) {
368
- super();
373
+ super(fs, path);
369
374
 
370
375
  /*
371
376
  Note: