@zenfs/core 1.2.7 → 1.2.9

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.
@@ -12,8 +12,9 @@ export type OptionsConfig<T> = {
12
12
  type: OptionType | readonly OptionType[];
13
13
  /**
14
14
  * Description of the option. Used in error messages and documentation.
15
+ * @deprecated
15
16
  */
16
- description: string;
17
+ description?: string;
17
18
  /**
18
19
  * Whether or not the option is required (optional can be set to null or undefined). Defaults to false.
19
20
  */
@@ -6,6 +6,10 @@ import type { IndexData } from './file_index.js';
6
6
  * Configuration options for FetchFS.
7
7
  */
8
8
  export interface FetchOptions {
9
+ /**
10
+ * Options to pass through to fetch calls
11
+ */
12
+ requestInit?: RequestInit;
9
13
  /**
10
14
  * URL to a file index as a JSON file or the file index object itself.
11
15
  * Defaults to `index.json`.
@@ -37,8 +41,9 @@ export interface FetchOptions {
37
41
  */
38
42
  export declare class FetchFS extends IndexFS {
39
43
  readonly baseUrl: string;
44
+ readonly requestInit?: RequestInit;
40
45
  ready(): Promise<void>;
41
- constructor({ index, baseUrl }: FetchOptions);
46
+ constructor({ index, baseUrl, requestInit }: FetchOptions);
42
47
  metadata(): FileSystemMetadata;
43
48
  /**
44
49
  * Preload the `path` into the index.
@@ -56,12 +61,14 @@ declare const _Fetch: {
56
61
  readonly index: {
57
62
  readonly type: readonly ["string", "object"];
58
63
  readonly required: false;
59
- readonly description: "URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.";
60
64
  };
61
65
  readonly baseUrl: {
62
66
  readonly type: "string";
63
67
  readonly required: false;
64
- readonly description: "Used as the URL prefix for fetched files. Default: Fetch files relative to the index.";
68
+ };
69
+ readonly requestInit: {
70
+ readonly type: "object";
71
+ readonly required: false;
65
72
  };
66
73
  };
67
74
  readonly isAvailable: () => boolean;
@@ -1,7 +1,7 @@
1
1
  import { Errno, ErrnoError } from '../error.js';
2
2
  import { IndexFS } from './file_index.js';
3
- async function fetchFile(path, type) {
4
- const response = await fetch(path).catch((e) => {
3
+ async function fetchFile(path, type, init) {
4
+ const response = await fetch(path, init).catch((e) => {
5
5
  throw new ErrnoError(Errno.EIO, e.message, path);
6
6
  });
7
7
  if (!response.ok) {
@@ -57,13 +57,14 @@ export class FetchFS extends IndexFS {
57
57
  await this.getData(path, stats);
58
58
  }
59
59
  }
60
- constructor({ index = 'index.json', baseUrl = '' }) {
60
+ constructor({ index = 'index.json', baseUrl = '', requestInit }) {
61
61
  // prefix url must end in a directory separator.
62
62
  if (baseUrl.at(-1) != '/') {
63
63
  baseUrl += '/';
64
64
  }
65
- super(typeof index != 'string' ? index : fetchFile(baseUrl + index, 'json'));
65
+ super(typeof index != 'string' ? index : fetchFile(baseUrl + index, 'json', requestInit));
66
66
  this.baseUrl = baseUrl;
67
+ this.requestInit = requestInit;
67
68
  }
68
69
  metadata() {
69
70
  return {
@@ -93,7 +94,7 @@ export class FetchFS extends IndexFS {
93
94
  if (stats.fileData) {
94
95
  return stats.fileData;
95
96
  }
96
- const data = await fetchFile(this.baseUrl + (path.startsWith('/') ? path.slice(1) : path), 'buffer');
97
+ const data = await fetchFile(this.baseUrl + (path.startsWith('/') ? path.slice(1) : path), 'buffer', this.requestInit);
97
98
  stats.fileData = data;
98
99
  return data;
99
100
  }
@@ -107,16 +108,9 @@ export class FetchFS extends IndexFS {
107
108
  const _Fetch = {
108
109
  name: 'Fetch',
109
110
  options: {
110
- index: {
111
- type: ['string', 'object'],
112
- required: false,
113
- description: 'URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.',
114
- },
115
- baseUrl: {
116
- type: 'string',
117
- required: false,
118
- description: 'Used as the URL prefix for fetched files. Default: Fetch files relative to the index.',
119
- },
111
+ index: { type: ['string', 'object'], required: false },
112
+ baseUrl: { type: 'string', required: false },
113
+ requestInit: { type: 'object', required: false },
120
114
  },
121
115
  isAvailable() {
122
116
  return typeof globalThis.fetch == 'function';
@@ -22,7 +22,6 @@ declare const _InMemory: {
22
22
  readonly name: {
23
23
  readonly type: "string";
24
24
  readonly required: false;
25
- readonly description: "The name of the store";
26
25
  };
27
26
  };
28
27
  readonly create: ({ name }: {
@@ -26,11 +26,7 @@ const _InMemory = {
26
26
  return true;
27
27
  },
28
28
  options: {
29
- name: {
30
- type: 'string',
31
- required: false,
32
- description: 'The name of the store',
33
- },
29
+ name: { type: 'string', required: false },
34
30
  },
35
31
  create({ name }) {
36
32
  const fs = new StoreFS(new InMemoryStore(name));
@@ -110,13 +110,11 @@ declare const _Port: {
110
110
  port: {
111
111
  type: "object";
112
112
  required: true;
113
- description: string;
114
113
  validator(port: RPC.Port): void;
115
114
  };
116
115
  timeout: {
117
116
  type: "number";
118
117
  required: false;
119
- description: string;
120
118
  };
121
119
  };
122
120
  isAvailable(): boolean;
@@ -214,7 +214,6 @@ const _Port = {
214
214
  port: {
215
215
  type: 'object',
216
216
  required: true,
217
- description: 'The target port that you want to connect to',
218
217
  validator(port) {
219
218
  // Check for a `postMessage` function.
220
219
  if (typeof port?.postMessage != 'function') {
@@ -225,7 +224,6 @@ const _Port = {
225
224
  timeout: {
226
225
  type: 'number',
227
226
  required: false,
228
- description: 'How long to wait before the request times out',
229
227
  },
230
228
  },
231
229
  isAvailable() {
@@ -642,17 +642,17 @@ export class StoreFS extends FileSystem {
642
642
  async commitNew(path, type, mode, data) {
643
643
  const env_15 = { stack: [], error: void 0, hasError: false };
644
644
  try {
645
- const tx = __addDisposableResource(env_15, this.store.transaction(), true);
646
- const parentPath = dirname(path), parent = await this.findINode(tx, parentPath);
647
- const fname = basename(path), listing = await this.getDirListing(tx, parent, parentPath);
648
645
  /*
649
646
  The root always exists.
650
647
  If we don't check this prior to taking steps below,
651
- we will create a file with name '' in root should path == '/'.
648
+ we will create a file with name '' in root if path is '/'.
652
649
  */
653
- if (path === '/') {
650
+ if (path == '/') {
654
651
  throw ErrnoError.With('EEXIST', path, 'commitNew');
655
652
  }
653
+ const tx = __addDisposableResource(env_15, this.store.transaction(), true);
654
+ const parentPath = dirname(path), parent = await this.findINode(tx, parentPath);
655
+ const fname = basename(path), listing = await this.getDirListing(tx, parent, parentPath);
656
656
  // Check if file already exists.
657
657
  if (listing[fname]) {
658
658
  await tx.abort();
@@ -693,17 +693,17 @@ export class StoreFS extends FileSystem {
693
693
  commitNewSync(path, type, mode, data = new Uint8Array()) {
694
694
  const env_16 = { stack: [], error: void 0, hasError: false };
695
695
  try {
696
- const tx = __addDisposableResource(env_16, this.store.transaction(), false);
697
- const parentPath = dirname(path), parent = this.findINodeSync(tx, parentPath);
698
- const fname = basename(path), listing = this.getDirListingSync(tx, parent, parentPath);
699
696
  /*
700
697
  The root always exists.
701
698
  If we don't check this prior to taking steps below,
702
- we will create a file with name '' in root should p == '/'.
699
+ we will create a file with name '' in root if path is '/'.
703
700
  */
704
- if (path === '/') {
701
+ if (path == '/') {
705
702
  throw ErrnoError.With('EEXIST', path, 'commitNew');
706
703
  }
704
+ const tx = __addDisposableResource(env_16, this.store.transaction(), false);
705
+ const parentPath = dirname(path), parent = this.findINodeSync(tx, parentPath);
706
+ const fname = basename(path), listing = this.getDirListingSync(tx, parent, parentPath);
707
707
  // Check if file already exists.
708
708
  if (listing[fname]) {
709
709
  throw ErrnoError.With('EEXIST', path, 'commitNew');
package/dist/config.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';
2
2
  import { credentials } from './credentials.js';
3
- import { DeviceFS, fullDevice, nullDevice, randomDevice, zeroDevice } from './devices.js';
3
+ import { DeviceFS } from './devices.js';
4
4
  import * as cache from './emulation/cache.js';
5
- import * as fs from './emulation/index.js';
6
5
  import { config } from './emulation/config.js';
6
+ import * as fs from './emulation/index.js';
7
7
  import { Errno, ErrnoError } from './error.js';
8
8
  import { FileSystem } from './filesystem.js';
9
9
  function isMountConfig(arg) {
@@ -60,6 +60,26 @@ export async function configureSingle(configuration) {
60
60
  fs.umount('/');
61
61
  fs.mount('/', resolved);
62
62
  }
63
+ /**
64
+ * Like `fs.mount`, but it also creates missing directories.
65
+ * @privateRemarks
66
+ * This is implemented as a separate function to avoid a circular dependency between emulation/shared.ts and other emulation layer files.
67
+ * @internal
68
+ */
69
+ async function mount(path, mount) {
70
+ if (path == '/') {
71
+ fs.mount(path, mount);
72
+ return;
73
+ }
74
+ const stats = await fs.promises.stat(path).catch(() => null);
75
+ if (!stats) {
76
+ await fs.promises.mkdir(path, { recursive: true });
77
+ }
78
+ else if (!stats.isDirectory()) {
79
+ throw ErrnoError.With('ENOTDIR', path, 'configure');
80
+ }
81
+ fs.mount(path, mount);
82
+ }
63
83
  /**
64
84
  * Configures ZenFS with `configuration`
65
85
  * @see Configuration
@@ -74,16 +94,15 @@ export async function configure(configuration) {
74
94
  config.syncImmediately = !configuration.onlySyncOnClose;
75
95
  if (configuration.addDevices) {
76
96
  const devfs = new DeviceFS();
77
- devfs.createDevice('/null', nullDevice);
78
- devfs.createDevice('/zero', zeroDevice);
79
- devfs.createDevice('/full', fullDevice);
80
- devfs.createDevice('/random', randomDevice);
97
+ devfs.addDefaults();
81
98
  await devfs.ready();
82
- fs.mount('/dev', devfs);
99
+ await mount('/dev', devfs);
83
100
  }
84
101
  if (!configuration.mounts) {
85
102
  return;
86
103
  }
104
+ const toMount = [];
105
+ let unmountRoot = false;
87
106
  for (const [point, mountConfig] of Object.entries(configuration.mounts)) {
88
107
  if (!point.startsWith('/')) {
89
108
  throw new ErrnoError(Errno.EINVAL, 'Mount points must have absolute paths');
@@ -91,7 +110,11 @@ export async function configure(configuration) {
91
110
  if (isBackendConfig(mountConfig)) {
92
111
  mountConfig.disableAsyncCache ?? (mountConfig.disableAsyncCache = configuration.disableAsyncCache || false);
93
112
  }
94
- configuration.mounts[point] = await resolveMountConfig(mountConfig);
113
+ if (point == '/')
114
+ unmountRoot = true;
115
+ toMount.push([point, await resolveMountConfig(mountConfig)]);
95
116
  }
96
- fs.mountObject(configuration.mounts);
117
+ if (unmountRoot)
118
+ fs.umount('/');
119
+ await Promise.all(toMount.map(([point, fs]) => mount(point, fs)));
97
120
  }
@@ -12,4 +12,7 @@ export interface Credentials {
12
12
  egid: number;
13
13
  }
14
14
  export declare const credentials: Credentials;
15
+ /**
16
+ * @deprecated
17
+ */
15
18
  export declare const rootCredentials: Credentials;
@@ -6,6 +6,9 @@ export const credentials = {
6
6
  euid: 0,
7
7
  egid: 0,
8
8
  };
9
+ /**
10
+ * @deprecated
11
+ */
9
12
  export const rootCredentials = {
10
13
  uid: 0,
11
14
  gid: 0,
package/dist/devices.d.ts CHANGED
@@ -8,9 +8,10 @@ import type { Ino } from './inode.js';
8
8
  /**
9
9
  * A device
10
10
  * @todo Maybe add major/minor number or some other device information, like a UUID?
11
- * @experimental
11
+ * @privateRemarks
12
+ * UUIDs were considered, however they don't make sense without an easy mechanism for persistance
12
13
  */
13
- export interface Device {
14
+ export interface Device<TData = any> {
14
15
  /**
15
16
  * The device's driver
16
17
  */
@@ -19,34 +20,64 @@ export interface Device {
19
20
  * Which inode the device is assigned
20
21
  */
21
22
  ino: Ino;
23
+ /**
24
+ * Data associated with a device.
25
+ * This is meant to be used by device drivers.
26
+ * @experimental
27
+ */
28
+ data: TData;
29
+ /**
30
+ * Major device number
31
+ * @experimental
32
+ */
33
+ major: number;
34
+ /**
35
+ * Minor device number
36
+ * @experimental
37
+ */
38
+ minor: number;
22
39
  }
23
40
  /**
24
41
  * A device driver
25
- * @experimental
26
42
  */
27
- export interface DeviceDriver {
43
+ export interface DeviceDriver<TData = any> {
28
44
  /**
29
45
  * The name of the device driver
30
46
  */
31
47
  name: string;
32
48
  /**
33
49
  * Whether the device is buffered (a "block" device) or unbuffered (a "character" device)
50
+ * @default false
34
51
  */
35
- isBuffered: boolean;
52
+ isBuffered?: boolean;
53
+ /**
54
+ * Initializes a new device.
55
+ * @returns `Device.data`
56
+ * @experimental
57
+ */
58
+ init?(ino: Ino): {
59
+ data?: TData;
60
+ minor?: number;
61
+ major?: number;
62
+ };
36
63
  /**
37
64
  * Synchronously read from the device
65
+ * @group File operations
38
66
  */
39
67
  read(file: DeviceFile, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
40
68
  /**
41
69
  * Synchronously write to the device
70
+ * @group File operations
42
71
  */
43
72
  write(file: DeviceFile, buffer: Uint8Array, offset: number, length: number, position?: number): number;
44
73
  /**
45
74
  * Sync the device
75
+ * @group File operations
46
76
  */
47
77
  sync?(file: DeviceFile): void;
48
78
  /**
49
79
  * Close the device
80
+ * @group File operations
50
81
  */
51
82
  close?(file: DeviceFile): void;
52
83
  }
@@ -55,7 +86,6 @@ export interface DeviceDriver {
55
86
  * This class only does some simple things:
56
87
  * It implements `truncate` using `write` and it has non-device methods throw.
57
88
  * It is up to device drivers to implement the rest of the functionality.
58
- * @experimental
59
89
  */
60
90
  export declare class DeviceFile extends File {
61
91
  fs: DeviceFS;
@@ -86,11 +116,18 @@ export declare class DeviceFile extends File {
86
116
  _setTypeSync(): void;
87
117
  }
88
118
  /**
89
- * @experimental
119
+ * A temporary file system that manages and interfaces with devices
90
120
  */
91
121
  export declare class DeviceFS extends StoreFS<InMemoryStore> {
92
- protected readonly devices: Map<string, Device>;
93
- createDevice(path: string, driver: DeviceDriver): Device;
122
+ protected readonly devices: Map<string, Device<any>>;
123
+ /**
124
+ * Creates a new device at `path` relative to the `DeviceFS` root.
125
+ */
126
+ createDevice<TData = any>(path: string, driver: DeviceDriver<TData>): Device<TData | Record<string, never>>;
127
+ /**
128
+ * Adds default devices
129
+ */
130
+ addDefaults(): void;
94
131
  constructor();
95
132
  rename(oldPath: string, newPath: string): Promise<void>;
96
133
  renameSync(oldPath: string, newPath: string): void;
@@ -150,9 +187,9 @@ export declare const randomDevice: DeviceDriver;
150
187
  * @experimental
151
188
  */
152
189
  declare const _default: {
153
- null: DeviceDriver;
154
- zero: DeviceDriver;
155
- full: DeviceDriver;
156
- random: DeviceDriver;
190
+ null: DeviceDriver<any>;
191
+ zero: DeviceDriver<any>;
192
+ full: DeviceDriver<any>;
193
+ random: DeviceDriver<any>;
157
194
  };
158
195
  export default _default;
package/dist/devices.js CHANGED
@@ -1,3 +1,6 @@
1
+ /*
2
+ This is a great resource: https://www.kernel.org/doc/html/latest/admin-guide/devices.html
3
+ */
1
4
  var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
5
  if (value !== null && value !== void 0) {
3
6
  if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
@@ -57,7 +60,6 @@ import { basename, dirname } from './emulation/path.js';
57
60
  * This class only does some simple things:
58
61
  * It implements `truncate` using `write` and it has non-device methods throw.
59
62
  * It is up to device drivers to implement the rest of the functionality.
60
- * @experimental
61
63
  */
62
64
  export class DeviceFile extends File {
63
65
  constructor(fs, path, device) {
@@ -142,9 +144,12 @@ export class DeviceFile extends File {
142
144
  }
143
145
  }
144
146
  /**
145
- * @experimental
147
+ * A temporary file system that manages and interfaces with devices
146
148
  */
147
149
  export class DeviceFS extends StoreFS {
150
+ /**
151
+ * Creates a new device at `path` relative to the `DeviceFS` root.
152
+ */
148
153
  createDevice(path, driver) {
149
154
  if (this.existsSync(path)) {
150
155
  throw ErrnoError.With('EEXIST', path, 'mknod');
@@ -155,10 +160,23 @@ export class DeviceFS extends StoreFS {
155
160
  const dev = {
156
161
  driver,
157
162
  ino,
163
+ data: {},
164
+ minor: 0,
165
+ major: 0,
166
+ ...driver.init?.(ino),
158
167
  };
159
168
  this.devices.set(path, dev);
160
169
  return dev;
161
170
  }
171
+ /**
172
+ * Adds default devices
173
+ */
174
+ addDefaults() {
175
+ this.createDevice('/null', nullDevice);
176
+ this.createDevice('/zero', zeroDevice);
177
+ this.createDevice('/full', fullDevice);
178
+ this.createDevice('/random', randomDevice);
179
+ }
162
180
  constructor() {
163
181
  super(new InMemoryStore('devfs'));
164
182
  this.devices = new Map();
@@ -332,7 +350,9 @@ function defaultWrite(file, buffer, offset, length) {
332
350
  */
333
351
  export const nullDevice = {
334
352
  name: 'null',
335
- isBuffered: false,
353
+ init() {
354
+ return { major: 1, minor: 3 };
355
+ },
336
356
  read() {
337
357
  return 0;
338
358
  },
@@ -350,7 +370,9 @@ export const nullDevice = {
350
370
  */
351
371
  export const zeroDevice = {
352
372
  name: 'zero',
353
- isBuffered: false,
373
+ init() {
374
+ return { major: 1, minor: 5 };
375
+ },
354
376
  read(file, buffer, offset = 0, length = buffer.byteLength) {
355
377
  const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
356
378
  for (let i = offset; i < offset + length; i++) {
@@ -369,7 +391,9 @@ export const zeroDevice = {
369
391
  */
370
392
  export const fullDevice = {
371
393
  name: 'full',
372
- isBuffered: false,
394
+ init() {
395
+ return { major: 1, minor: 7 };
396
+ },
373
397
  read(file, buffer, offset = 0, length = buffer.byteLength) {
374
398
  const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
375
399
  for (let i = offset; i < offset + length; i++) {
@@ -390,7 +414,9 @@ export const fullDevice = {
390
414
  */
391
415
  export const randomDevice = {
392
416
  name: 'random',
393
- isBuffered: false,
417
+ init() {
418
+ return { major: 1, minor: 8 };
419
+ },
394
420
  read(file, buffer, offset = 0, length = buffer.byteLength) {
395
421
  const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
396
422
  for (let i = offset; i < offset + length; i++) {
@@ -53,11 +53,11 @@ import '../polyfills.js';
53
53
  import { BigIntStats } from '../stats.js';
54
54
  import { decodeUTF8, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
55
55
  import * as cache from './cache.js';
56
+ import { config } from './config.js';
56
57
  import * as constants from './constants.js';
57
58
  import { Dir, Dirent } from './dir.js';
58
59
  import { dirname, join, parse } from './path.js';
59
- import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
60
- import { config } from './config.js';
60
+ import { _statfs, fd2file, fdMap, file2fd, fixError, resolveMount } from './shared.js';
61
61
  import { ReadStream, WriteStream } from './streams.js';
62
62
  import { FSWatcher, emitChange } from './watchers.js';
63
63
  export * as constants from './constants.js';
@@ -585,7 +585,7 @@ export async function rmdir(path) {
585
585
  try {
586
586
  const stats = await (cache.getStats(path) || fs.stat(resolved));
587
587
  if (!stats) {
588
- throw ErrnoError.With('ENOENT', path, 'readdir');
588
+ throw ErrnoError.With('ENOENT', path, 'rmdir');
589
589
  }
590
590
  if (!stats.isDirectory()) {
591
591
  throw ErrnoError.With('ENOTDIR', resolved, 'rmdir');
@@ -655,16 +655,6 @@ export async function readdir(path, options) {
655
655
  throw ErrnoError.With('ENOTDIR', path, 'readdir');
656
656
  }
657
657
  const entries = await fs.readdir(resolved).catch(handleError);
658
- for (const point of mounts.keys()) {
659
- if (point.startsWith(path)) {
660
- const entry = point.slice(path.length);
661
- if (entry.includes('/') || entry.length == 0) {
662
- // ignore FSs mounted in subdirectories and any FS mounted to `path`.
663
- continue;
664
- }
665
- entries.push(entry);
666
- }
667
- }
668
658
  const values = [];
669
659
  const addEntry = async (entry) => {
670
660
  let entryStats;
@@ -21,7 +21,7 @@ export declare function mount(mountPoint: string, fs: FileSystem): void;
21
21
  */
22
22
  export declare function umount(mountPoint: string): void;
23
23
  /**
24
- * Gets the internal FileSystem for the path, then returns it along with the path relative to the FS' root
24
+ * Gets the internal `FileSystem` for the path, then returns it along with the path relative to the FS' root
25
25
  */
26
26
  export declare function resolveMount(path: string): {
27
27
  fs: FileSystem;
@@ -38,6 +38,9 @@ export declare function fixPaths(text: string, paths: Record<string, string>): s
38
38
  * @hidden
39
39
  */
40
40
  export declare function fixError<E extends ErrnoError>(e: E, paths: Record<string, string>): E;
41
+ /**
42
+ * @deprecated
43
+ */
41
44
  export declare function mountObject(mounts: MountObject): void;
42
45
  /**
43
46
  * @hidden
@@ -43,7 +43,7 @@ export function mount(mountPoint, fs) {
43
43
  */
44
44
  export function umount(mountPoint) {
45
45
  if (mountPoint[0] !== '/') {
46
- mountPoint = `/${mountPoint}`;
46
+ mountPoint = '/' + mountPoint;
47
47
  }
48
48
  mountPoint = resolve(mountPoint);
49
49
  if (!mounts.has(mountPoint)) {
@@ -52,11 +52,10 @@ export function umount(mountPoint) {
52
52
  mounts.delete(mountPoint);
53
53
  }
54
54
  /**
55
- * Gets the internal FileSystem for the path, then returns it along with the path relative to the FS' root
55
+ * Gets the internal `FileSystem` for the path, then returns it along with the path relative to the FS' root
56
56
  */
57
57
  export function resolveMount(path) {
58
58
  path = normalizePath(path);
59
- // Maybe do something for devices here
60
59
  const sortedMounts = [...mounts].sort((a, b) => (a[0].length > b[0].length ? -1 : 1)); // descending order of the string length
61
60
  for (const [mountPoint, fs] of sortedMounts) {
62
61
  // We know path is normalized, so it would be a substring of the mount point.
@@ -91,6 +90,9 @@ export function fixError(e, paths) {
91
90
  e.message = fixPaths(e.message, paths);
92
91
  return e;
93
92
  }
93
+ /**
94
+ * @deprecated
95
+ */
94
96
  export function mountObject(mounts) {
95
97
  if ('/' in mounts) {
96
98
  umount('/');
@@ -50,13 +50,13 @@ import { Errno, ErrnoError } from '../error.js';
50
50
  import { flagToMode, isAppendable, isExclusive, isReadable, isTruncating, isWriteable, parseFlag } from '../file.js';
51
51
  import { BigIntStats } from '../stats.js';
52
52
  import { decodeUTF8, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
53
+ import * as cache from './cache.js';
54
+ import { config } from './config.js';
53
55
  import * as constants from './constants.js';
54
56
  import { Dir, Dirent } from './dir.js';
55
57
  import { dirname, join, parse } from './path.js';
56
- import { _statfs, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
57
- import { config } from './config.js';
58
+ import { _statfs, fd2file, fdMap, file2fd, fixError, resolveMount } from './shared.js';
58
59
  import { emitChange } from './watchers.js';
59
- import * as cache from './cache.js';
60
60
  export function renameSync(oldPath, newPath) {
61
61
  oldPath = normalizePath(oldPath);
62
62
  newPath = normalizePath(newPath);
@@ -459,17 +459,6 @@ export function readdirSync(path, options) {
459
459
  catch (e) {
460
460
  throw fixError(e, { [resolved]: path });
461
461
  }
462
- for (const mount of mounts.keys()) {
463
- if (!mount.startsWith(path)) {
464
- continue;
465
- }
466
- const entry = mount.slice(path.length);
467
- if (entry.includes('/') || entry.length == 0) {
468
- // ignore FSs mounted in subdirectories and any FS mounted to `path`.
469
- continue;
470
- }
471
- entries.push(entry);
472
- }
473
462
  // Iterate over entries and handle recursive case if needed
474
463
  const values = [];
475
464
  for (const entry of entries) {
@@ -90,8 +90,8 @@ export function Async(FS) {
90
90
  const sync = this._sync['store'].transaction();
91
91
  const async = this['store'].transaction();
92
92
  const promises = [];
93
- for (const key of sync.keysSync()) {
94
- promises.push(async.set(key, sync.getSync(key)));
93
+ for (const key of await async.keys()) {
94
+ promises.push(async.get(key).then(data => sync.setSync(key, data)));
95
95
  }
96
96
  await Promise.all(promises);
97
97
  this._isInitialized = true;