@zenfs/core 1.2.9 → 1.3.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.
- package/dist/backends/fetch.js +1 -1
- package/dist/backends/memory.d.ts +1 -2
- package/dist/backends/overlay.js +2 -3
- package/dist/backends/port/fs.d.ts +2 -15
- package/dist/backends/store/fs.d.ts +17 -28
- package/dist/backends/store/fs.js +169 -191
- package/dist/backends/store/simple.d.ts +20 -21
- package/dist/backends/store/simple.js +24 -24
- package/dist/backends/store/store.d.ts +22 -23
- package/dist/backends/store/store.js +6 -6
- package/dist/config.d.ts +8 -0
- package/dist/config.js +2 -1
- package/dist/devices.d.ts +2 -3
- package/dist/emulation/cache.d.ts +40 -31
- package/dist/emulation/cache.js +62 -53
- package/dist/emulation/index.d.ts +1 -1
- package/dist/emulation/index.js +1 -1
- package/dist/emulation/promises.js +18 -17
- package/dist/emulation/shared.d.ts +6 -0
- package/dist/emulation/shared.js +13 -1
- package/dist/emulation/sync.d.ts +1 -1
- package/dist/emulation/sync.js +16 -15
- package/dist/file.d.ts +3 -15
- package/dist/file.js +7 -19
- package/dist/inode.d.ts +4 -13
- package/dist/inode.js +22 -29
- package/dist/mixins/async.d.ts +15 -10
- package/dist/mixins/async.js +3 -1
- package/dist/stats.js +30 -5
- package/dist/utils.d.ts +5 -7
- package/dist/utils.js +11 -20
- package/package.json +1 -1
- package/src/backends/fetch.ts +1 -1
- package/src/backends/memory.ts +1 -2
- package/src/backends/overlay.ts +2 -2
- package/src/backends/store/fs.ts +187 -220
- package/src/backends/store/simple.ts +36 -37
- package/src/backends/store/store.ts +25 -26
- package/src/config.ts +11 -1
- package/src/devices.ts +2 -3
- package/src/emulation/cache.ts +68 -60
- package/src/emulation/index.ts +1 -1
- package/src/emulation/promises.ts +20 -19
- package/src/emulation/shared.ts +13 -1
- package/src/emulation/sync.ts +16 -15
- package/src/file.ts +9 -21
- package/src/inode.ts +10 -31
- package/src/mixins/async.ts +27 -24
- package/src/stats.ts +47 -5
- package/src/utils.ts +11 -23
- package/tests/fs/dir.test.ts +21 -31
- package/tests/fs/directory.test.ts +6 -4
- package/tests/fs/links.test.ts +9 -2
- package/tests/fs/permissions.test.ts +2 -2
- package/tests/fs/stat.test.ts +42 -0
- package/tests/fs/times.test.ts +28 -28
- package/tests/setup/cow+fetch.ts +4 -2
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import type { Ino } from '../../inode.js';
|
|
2
1
|
import { SyncTransaction, type Store } from './store.js';
|
|
3
2
|
/**
|
|
4
3
|
* An interface for simple synchronous stores that don't have special support for transactions and such.
|
|
5
4
|
*/
|
|
6
5
|
export interface SimpleSyncStore extends Store {
|
|
7
|
-
keys(): Iterable<
|
|
8
|
-
get(
|
|
9
|
-
set(
|
|
10
|
-
delete(
|
|
6
|
+
keys(): Iterable<bigint>;
|
|
7
|
+
get(id: bigint): Uint8Array | undefined;
|
|
8
|
+
set(id: bigint, data: Uint8Array): void;
|
|
9
|
+
delete(id: bigint): void;
|
|
11
10
|
}
|
|
12
11
|
/**
|
|
13
12
|
* An interface for simple asynchronous stores that don't have special support for transactions and such.
|
|
@@ -15,15 +14,15 @@ export interface SimpleSyncStore extends Store {
|
|
|
15
14
|
*/
|
|
16
15
|
export declare abstract class SimpleAsyncStore implements SimpleSyncStore {
|
|
17
16
|
abstract name: string;
|
|
18
|
-
protected cache: Map<
|
|
17
|
+
protected cache: Map<bigint, Uint8Array>;
|
|
19
18
|
protected queue: Set<Promise<unknown>>;
|
|
20
|
-
protected abstract entries(): Promise<Iterable<[
|
|
21
|
-
keys(): Iterable<
|
|
22
|
-
get(
|
|
23
|
-
set(
|
|
24
|
-
protected abstract _set(ino:
|
|
25
|
-
delete(
|
|
26
|
-
protected abstract _delete(ino:
|
|
19
|
+
protected abstract entries(): Promise<Iterable<[bigint, Uint8Array]>>;
|
|
20
|
+
keys(): Iterable<bigint>;
|
|
21
|
+
get(id: bigint): Uint8Array | undefined;
|
|
22
|
+
set(id: bigint, data: Uint8Array): void;
|
|
23
|
+
protected abstract _set(ino: bigint, data: Uint8Array): Promise<void>;
|
|
24
|
+
delete(id: bigint): void;
|
|
25
|
+
protected abstract _delete(ino: bigint): Promise<void>;
|
|
27
26
|
clearSync(): void;
|
|
28
27
|
abstract clear(): Promise<void>;
|
|
29
28
|
sync(): Promise<void>;
|
|
@@ -39,16 +38,16 @@ export declare class SimpleTransaction extends SyncTransaction<SimpleSyncStore>
|
|
|
39
38
|
* Stores data in the keys we modify prior to modifying them.
|
|
40
39
|
* Allows us to roll back commits.
|
|
41
40
|
*/
|
|
42
|
-
protected originalData: Map<
|
|
41
|
+
protected originalData: Map<bigint, Uint8Array | void>;
|
|
43
42
|
/**
|
|
44
43
|
* List of keys modified in this transaction, if any.
|
|
45
44
|
*/
|
|
46
|
-
protected modifiedKeys: Set<
|
|
45
|
+
protected modifiedKeys: Set<bigint>;
|
|
47
46
|
protected store: SimpleSyncStore;
|
|
48
|
-
keysSync(): Iterable<
|
|
49
|
-
getSync(
|
|
50
|
-
setSync(
|
|
51
|
-
removeSync(
|
|
47
|
+
keysSync(): Iterable<bigint>;
|
|
48
|
+
getSync(id: bigint): Uint8Array;
|
|
49
|
+
setSync(id: bigint, data: Uint8Array): void;
|
|
50
|
+
removeSync(id: bigint): void;
|
|
52
51
|
commitSync(): void;
|
|
53
52
|
abortSync(): void;
|
|
54
53
|
/**
|
|
@@ -57,10 +56,10 @@ export declare class SimpleTransaction extends SyncTransaction<SimpleSyncStore>
|
|
|
57
56
|
* prevent needless `get` requests if the program modifies the data later
|
|
58
57
|
* on during the transaction.
|
|
59
58
|
*/
|
|
60
|
-
protected stashOldValue(
|
|
59
|
+
protected stashOldValue(id: bigint, value?: Uint8Array): void;
|
|
61
60
|
/**
|
|
62
61
|
* Marks `ino` as modified, and stashes its value if it has not been
|
|
63
62
|
* stashed already.
|
|
64
63
|
*/
|
|
65
|
-
protected markModified(
|
|
64
|
+
protected markModified(id: bigint): void;
|
|
66
65
|
}
|
|
@@ -11,16 +11,16 @@ export class SimpleAsyncStore {
|
|
|
11
11
|
keys() {
|
|
12
12
|
return this.cache.keys();
|
|
13
13
|
}
|
|
14
|
-
get(
|
|
15
|
-
return this.cache.get(
|
|
14
|
+
get(id) {
|
|
15
|
+
return this.cache.get(id);
|
|
16
16
|
}
|
|
17
|
-
set(
|
|
18
|
-
this.cache.set(
|
|
19
|
-
this.queue.add(this._set(
|
|
17
|
+
set(id, data) {
|
|
18
|
+
this.cache.set(id, data);
|
|
19
|
+
this.queue.add(this._set(id, data));
|
|
20
20
|
}
|
|
21
|
-
delete(
|
|
22
|
-
this.cache.delete(
|
|
23
|
-
this.queue.add(this._delete(
|
|
21
|
+
delete(id) {
|
|
22
|
+
this.cache.delete(id);
|
|
23
|
+
this.queue.add(this._delete(id));
|
|
24
24
|
}
|
|
25
25
|
clearSync() {
|
|
26
26
|
this.cache.clear();
|
|
@@ -61,18 +61,18 @@ export class SimpleTransaction extends SyncTransaction {
|
|
|
61
61
|
keysSync() {
|
|
62
62
|
return this.store.keys();
|
|
63
63
|
}
|
|
64
|
-
getSync(
|
|
65
|
-
const val = this.store.get(
|
|
66
|
-
this.stashOldValue(
|
|
64
|
+
getSync(id) {
|
|
65
|
+
const val = this.store.get(id);
|
|
66
|
+
this.stashOldValue(id, val);
|
|
67
67
|
return val;
|
|
68
68
|
}
|
|
69
|
-
setSync(
|
|
70
|
-
this.markModified(
|
|
71
|
-
return this.store.set(
|
|
69
|
+
setSync(id, data) {
|
|
70
|
+
this.markModified(id);
|
|
71
|
+
return this.store.set(id, data);
|
|
72
72
|
}
|
|
73
|
-
removeSync(
|
|
74
|
-
this.markModified(
|
|
75
|
-
this.store.delete(
|
|
73
|
+
removeSync(id) {
|
|
74
|
+
this.markModified(id);
|
|
75
|
+
this.store.delete(id);
|
|
76
76
|
}
|
|
77
77
|
commitSync() {
|
|
78
78
|
this.done = true;
|
|
@@ -101,20 +101,20 @@ export class SimpleTransaction extends SyncTransaction {
|
|
|
101
101
|
* prevent needless `get` requests if the program modifies the data later
|
|
102
102
|
* on during the transaction.
|
|
103
103
|
*/
|
|
104
|
-
stashOldValue(
|
|
104
|
+
stashOldValue(id, value) {
|
|
105
105
|
// Keep only the earliest value in the transaction.
|
|
106
|
-
if (!this.originalData.has(
|
|
107
|
-
this.originalData.set(
|
|
106
|
+
if (!this.originalData.has(id)) {
|
|
107
|
+
this.originalData.set(id, value);
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
111
111
|
* Marks `ino` as modified, and stashes its value if it has not been
|
|
112
112
|
* stashed already.
|
|
113
113
|
*/
|
|
114
|
-
markModified(
|
|
115
|
-
this.modifiedKeys.add(
|
|
116
|
-
if (!this.originalData.has(
|
|
117
|
-
this.originalData.set(
|
|
114
|
+
markModified(id) {
|
|
115
|
+
this.modifiedKeys.add(id);
|
|
116
|
+
if (!this.originalData.has(id)) {
|
|
117
|
+
this.originalData.set(id, this.store.get(id));
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Ino } from '../../inode.js';
|
|
2
1
|
import '../../polyfills.js';
|
|
3
2
|
/**
|
|
4
3
|
* Represents a key-value store.
|
|
@@ -38,45 +37,45 @@ export declare abstract class Transaction<T extends Store = Store> {
|
|
|
38
37
|
/**
|
|
39
38
|
* Gets all of the keys
|
|
40
39
|
*/
|
|
41
|
-
abstract keys(): Promise<Iterable<
|
|
40
|
+
abstract keys(): Promise<Iterable<bigint>>;
|
|
42
41
|
/**
|
|
43
42
|
* Gets all of the keys
|
|
44
43
|
*/
|
|
45
|
-
abstract keysSync(): Iterable<
|
|
44
|
+
abstract keysSync(): Iterable<bigint>;
|
|
46
45
|
/**
|
|
47
|
-
* Retrieves
|
|
48
|
-
* @param
|
|
46
|
+
* Retrieves data.
|
|
47
|
+
* @param id The key to look under for data.
|
|
49
48
|
*/
|
|
50
|
-
abstract get(
|
|
49
|
+
abstract get(id: bigint): Promise<Uint8Array>;
|
|
51
50
|
/**
|
|
52
|
-
* Retrieves
|
|
51
|
+
* Retrieves data.
|
|
53
52
|
* Throws an error if an error occurs or if the key does not exist.
|
|
54
|
-
* @param
|
|
53
|
+
* @param id The key to look under for data.
|
|
55
54
|
* @return The data stored under the key, or undefined if not present.
|
|
56
55
|
*/
|
|
57
|
-
abstract getSync(
|
|
56
|
+
abstract getSync(id: bigint): Uint8Array;
|
|
58
57
|
/**
|
|
59
|
-
* Adds the data to the store under
|
|
60
|
-
* @param
|
|
58
|
+
* Adds the data to the store under an id. Overwrites any existing data.
|
|
59
|
+
* @param id The key to add the data under.
|
|
61
60
|
* @param data The data to add to the store.
|
|
62
61
|
*/
|
|
63
|
-
abstract set(
|
|
62
|
+
abstract set(id: bigint, data: Uint8Array): Promise<void>;
|
|
64
63
|
/**
|
|
65
|
-
* Adds the data to the store under
|
|
66
|
-
* @param
|
|
64
|
+
* Adds the data to the store under and id.
|
|
65
|
+
* @param id The key to add the data under.
|
|
67
66
|
* @param data The data to add to the store.
|
|
68
67
|
*/
|
|
69
|
-
abstract setSync(
|
|
68
|
+
abstract setSync(id: bigint, data: Uint8Array): void;
|
|
70
69
|
/**
|
|
71
70
|
* Deletes the data at `ino`.
|
|
72
|
-
* @param
|
|
71
|
+
* @param id The key to delete from the store.
|
|
73
72
|
*/
|
|
74
|
-
abstract remove(
|
|
73
|
+
abstract remove(id: bigint): Promise<void>;
|
|
75
74
|
/**
|
|
76
75
|
* Deletes the data at `ino`.
|
|
77
|
-
* @param
|
|
76
|
+
* @param id The key to delete from the store.
|
|
78
77
|
*/
|
|
79
|
-
abstract removeSync(
|
|
78
|
+
abstract removeSync(id: bigint): void;
|
|
80
79
|
/**
|
|
81
80
|
* Commits the transaction.
|
|
82
81
|
*/
|
|
@@ -100,10 +99,10 @@ export declare abstract class Transaction<T extends Store = Store> {
|
|
|
100
99
|
* Transaction that implements asynchronous operations with synchronous ones
|
|
101
100
|
*/
|
|
102
101
|
export declare abstract class SyncTransaction<T extends Store = Store> extends Transaction<T> {
|
|
103
|
-
keys(): Promise<Iterable<
|
|
104
|
-
get(
|
|
105
|
-
set(
|
|
106
|
-
remove(
|
|
102
|
+
keys(): Promise<Iterable<bigint>>;
|
|
103
|
+
get(id: bigint): Promise<Uint8Array>;
|
|
104
|
+
set(id: bigint, data: Uint8Array): Promise<void>;
|
|
105
|
+
remove(id: bigint): Promise<void>;
|
|
107
106
|
commit(): Promise<void>;
|
|
108
107
|
abort(): Promise<void>;
|
|
109
108
|
}
|
|
@@ -32,14 +32,14 @@ export class SyncTransaction extends Transaction {
|
|
|
32
32
|
async keys() {
|
|
33
33
|
return this.keysSync();
|
|
34
34
|
}
|
|
35
|
-
async get(
|
|
36
|
-
return this.getSync(
|
|
35
|
+
async get(id) {
|
|
36
|
+
return this.getSync(id);
|
|
37
37
|
}
|
|
38
|
-
async set(
|
|
39
|
-
return this.setSync(
|
|
38
|
+
async set(id, data) {
|
|
39
|
+
return this.setSync(id, data);
|
|
40
40
|
}
|
|
41
|
-
async remove(
|
|
42
|
-
return this.removeSync(
|
|
41
|
+
async remove(id) {
|
|
42
|
+
return this.removeSync(id);
|
|
43
43
|
}
|
|
44
44
|
async commit() {
|
|
45
45
|
return this.commitSync();
|
package/dist/config.d.ts
CHANGED
|
@@ -45,6 +45,14 @@ export interface Configuration<T extends ConfigMounts> extends SharedConfig {
|
|
|
45
45
|
* @default false
|
|
46
46
|
*/
|
|
47
47
|
cacheStats: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* If true, enables caching realpath output
|
|
50
|
+
*
|
|
51
|
+
* This can increase performance.
|
|
52
|
+
* @experimental
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
cachePaths: boolean;
|
|
48
56
|
/**
|
|
49
57
|
* If true, disables *all* permissions checking.
|
|
50
58
|
*
|
package/dist/config.js
CHANGED
|
@@ -88,7 +88,8 @@ export async function configure(configuration) {
|
|
|
88
88
|
const uid = 'uid' in configuration ? configuration.uid || 0 : 0;
|
|
89
89
|
const gid = 'gid' in configuration ? configuration.gid || 0 : 0;
|
|
90
90
|
Object.assign(credentials, { uid, gid, suid: uid, sgid: gid, euid: uid, egid: gid });
|
|
91
|
-
cache.
|
|
91
|
+
cache.stats.isEnabled = configuration.cacheStats ?? false;
|
|
92
|
+
cache.paths.isEnabled = configuration.cachePaths ?? false;
|
|
92
93
|
config.checkAccess = !configuration.disableAccessChecks;
|
|
93
94
|
config.updateOnRead = !configuration.disableUpdateOnRead;
|
|
94
95
|
config.syncImmediately = !configuration.onlySyncOnClose;
|
package/dist/devices.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { StoreFS } from './backends/store/fs.js';
|
|
|
4
4
|
import { File } from './file.js';
|
|
5
5
|
import type { StatsLike } from './stats.js';
|
|
6
6
|
import { Stats } from './stats.js';
|
|
7
|
-
import type { Ino } from './inode.js';
|
|
8
7
|
/**
|
|
9
8
|
* A device
|
|
10
9
|
* @todo Maybe add major/minor number or some other device information, like a UUID?
|
|
@@ -19,7 +18,7 @@ export interface Device<TData = any> {
|
|
|
19
18
|
/**
|
|
20
19
|
* Which inode the device is assigned
|
|
21
20
|
*/
|
|
22
|
-
ino:
|
|
21
|
+
ino: bigint;
|
|
23
22
|
/**
|
|
24
23
|
* Data associated with a device.
|
|
25
24
|
* This is meant to be used by device drivers.
|
|
@@ -55,7 +54,7 @@ export interface DeviceDriver<TData = any> {
|
|
|
55
54
|
* @returns `Device.data`
|
|
56
55
|
* @experimental
|
|
57
56
|
*/
|
|
58
|
-
init?(ino:
|
|
57
|
+
init?(ino: bigint): {
|
|
59
58
|
data?: TData;
|
|
60
59
|
minor?: number;
|
|
61
60
|
major?: number;
|
|
@@ -1,33 +1,42 @@
|
|
|
1
1
|
import type { Stats } from '../stats.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
3
|
+
* Used for caching data
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare class Cache<T> {
|
|
7
|
+
isEnabled: boolean;
|
|
8
|
+
protected sync: Map<string, T>;
|
|
9
|
+
protected async: Map<string, Promise<T>>;
|
|
10
|
+
/**
|
|
11
|
+
* Gets data from the cache, if is exists and the cache is enabled.
|
|
12
|
+
*/
|
|
13
|
+
getSync(path: string): T | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Adds data if the cache is enabled
|
|
16
|
+
*/
|
|
17
|
+
setSync(path: string, value: T): void;
|
|
18
|
+
/**
|
|
19
|
+
* Clears the cache if it is enabled
|
|
20
|
+
*/
|
|
21
|
+
clearSync(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Gets data from the cache, if it exists and the cache is enabled.
|
|
24
|
+
*/
|
|
25
|
+
get(path: string): Promise<T> | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Adds data if the cache is enabled
|
|
28
|
+
*/
|
|
29
|
+
set(path: string, value: Promise<T>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Clears the cache if it is enabled
|
|
32
|
+
*/
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Used to cache
|
|
37
|
+
*/
|
|
38
|
+
export declare const stats: Cache<Stats>;
|
|
39
|
+
/**
|
|
40
|
+
* Used to cache realpath lookups
|
|
41
|
+
*/
|
|
42
|
+
export declare const paths: Cache<string>;
|
package/dist/emulation/cache.js
CHANGED
|
@@ -1,61 +1,70 @@
|
|
|
1
1
|
/* Experimental caching */
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Used for caching data
|
|
4
|
+
* @internal
|
|
4
5
|
*/
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
6
|
+
export class Cache {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.isEnabled = false;
|
|
9
|
+
this.sync = new Map();
|
|
10
|
+
this.async = new Map();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Gets data from the cache, if is exists and the cache is enabled.
|
|
14
|
+
*/
|
|
15
|
+
getSync(path) {
|
|
16
|
+
if (!this.isEnabled)
|
|
17
|
+
return;
|
|
18
|
+
return this.sync.get(path);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Adds data if the cache is enabled
|
|
22
|
+
*/
|
|
23
|
+
setSync(path, value) {
|
|
24
|
+
if (!this.isEnabled)
|
|
25
|
+
return;
|
|
26
|
+
this.sync.set(path, value);
|
|
27
|
+
this.async.set(path, Promise.resolve(value));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Clears the cache if it is enabled
|
|
31
|
+
*/
|
|
32
|
+
clearSync() {
|
|
33
|
+
if (!this.isEnabled)
|
|
34
|
+
return;
|
|
35
|
+
this.sync.clear();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets data from the cache, if it exists and the cache is enabled.
|
|
39
|
+
*/
|
|
40
|
+
get(path) {
|
|
41
|
+
if (!this.isEnabled)
|
|
42
|
+
return;
|
|
43
|
+
return this.async.get(path);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Adds data if the cache is enabled
|
|
47
|
+
*/
|
|
48
|
+
set(path, value) {
|
|
49
|
+
if (!this.isEnabled)
|
|
50
|
+
return;
|
|
51
|
+
this.async.set(path, value);
|
|
52
|
+
void value.then(v => this.sync.set(path, v));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Clears the cache if it is enabled
|
|
56
|
+
*/
|
|
57
|
+
clear() {
|
|
58
|
+
if (!this.isEnabled)
|
|
59
|
+
return;
|
|
60
|
+
this.async.clear();
|
|
61
|
+
}
|
|
28
62
|
}
|
|
29
63
|
/**
|
|
30
|
-
*
|
|
64
|
+
* Used to cache
|
|
31
65
|
*/
|
|
32
|
-
export
|
|
33
|
-
if (!isEnabled)
|
|
34
|
-
return;
|
|
35
|
-
statsSync.clear();
|
|
36
|
-
}
|
|
37
|
-
const stats = new Map();
|
|
38
|
-
/**
|
|
39
|
-
* Gets stats from the cache, if they exist and the cache is enabled.
|
|
40
|
-
*/
|
|
41
|
-
export function getStats(path) {
|
|
42
|
-
if (!isEnabled)
|
|
43
|
-
return;
|
|
44
|
-
return stats.get(path);
|
|
45
|
-
}
|
|
66
|
+
export const stats = new Cache();
|
|
46
67
|
/**
|
|
47
|
-
*
|
|
68
|
+
* Used to cache realpath lookups
|
|
48
69
|
*/
|
|
49
|
-
export
|
|
50
|
-
if (!isEnabled)
|
|
51
|
-
return;
|
|
52
|
-
stats.set(path, value);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Clears the cache if it is enabled
|
|
56
|
-
*/
|
|
57
|
-
export function clearStats() {
|
|
58
|
-
if (!isEnabled)
|
|
59
|
-
return;
|
|
60
|
-
stats.clear();
|
|
61
|
-
}
|
|
70
|
+
export const paths = new Cache();
|
|
@@ -4,5 +4,5 @@ export * as promises from './promises.js';
|
|
|
4
4
|
export * as constants from './constants.js';
|
|
5
5
|
export * from './streams.js';
|
|
6
6
|
export * from './dir.js';
|
|
7
|
-
export { mountObject, mounts, mount, umount } from './shared.js';
|
|
7
|
+
export { mountObject, mounts, mount, umount, _synced } from './shared.js';
|
|
8
8
|
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';
|
package/dist/emulation/index.js
CHANGED
|
@@ -4,5 +4,5 @@ export * as promises from './promises.js';
|
|
|
4
4
|
export * as constants from './constants.js';
|
|
5
5
|
export * from './streams.js';
|
|
6
6
|
export * from './dir.js';
|
|
7
|
-
export { mountObject, mounts, mount, umount } from './shared.js';
|
|
7
|
+
export { mountObject, mounts, mount, umount, _synced } from './shared.js';
|
|
8
8
|
export { Stats, StatsFs, BigIntStatsFs } from '../stats.js';
|
|
@@ -435,7 +435,7 @@ export async function unlink(path) {
|
|
|
435
435
|
path = normalizePath(path);
|
|
436
436
|
const { fs, path: resolved } = resolveMount(path);
|
|
437
437
|
try {
|
|
438
|
-
if (config.checkAccess && !(await (cache.
|
|
438
|
+
if (config.checkAccess && !(await (cache.stats.get(path) || fs.stat(resolved))).hasAccess(constants.W_OK)) {
|
|
439
439
|
throw ErrnoError.With('EACCES', resolved, 'unlink');
|
|
440
440
|
}
|
|
441
441
|
await fs.unlink(resolved);
|
|
@@ -583,7 +583,7 @@ export async function rmdir(path) {
|
|
|
583
583
|
path = await realpath(path);
|
|
584
584
|
const { fs, path: resolved } = resolveMount(path);
|
|
585
585
|
try {
|
|
586
|
-
const stats = await (cache.
|
|
586
|
+
const stats = await (cache.stats.get(path) || fs.stat(resolved));
|
|
587
587
|
if (!stats) {
|
|
588
588
|
throw ErrnoError.With('ENOENT', path, 'rmdir');
|
|
589
589
|
}
|
|
@@ -642,8 +642,8 @@ export async function readdir(path, options) {
|
|
|
642
642
|
throw fixError(e, { [resolved]: path });
|
|
643
643
|
};
|
|
644
644
|
const { fs, path: resolved } = resolveMount(path);
|
|
645
|
-
const _stats = cache.
|
|
646
|
-
cache.
|
|
645
|
+
const _stats = cache.stats.get(path) || fs.stat(resolved).catch(handleError);
|
|
646
|
+
cache.stats.set(path, _stats);
|
|
647
647
|
const stats = await _stats;
|
|
648
648
|
if (!stats) {
|
|
649
649
|
throw ErrnoError.With('ENOENT', path, 'readdir');
|
|
@@ -659,8 +659,8 @@ export async function readdir(path, options) {
|
|
|
659
659
|
const addEntry = async (entry) => {
|
|
660
660
|
let entryStats;
|
|
661
661
|
if (options?.recursive || options?.withFileTypes) {
|
|
662
|
-
const _entryStats = cache.
|
|
663
|
-
cache.
|
|
662
|
+
const _entryStats = cache.stats.get(join(path, entry)) || fs.stat(join(resolved, entry)).catch(handleError);
|
|
663
|
+
cache.stats.set(join(path, entry), _entryStats);
|
|
664
664
|
entryStats = await _entryStats;
|
|
665
665
|
}
|
|
666
666
|
if (options?.withFileTypes) {
|
|
@@ -690,7 +690,7 @@ export async function readdir(path, options) {
|
|
|
690
690
|
};
|
|
691
691
|
await Promise.all(entries.map(addEntry));
|
|
692
692
|
if (!options?._isIndirect) {
|
|
693
|
-
cache.
|
|
693
|
+
cache.stats.clear();
|
|
694
694
|
}
|
|
695
695
|
return values;
|
|
696
696
|
}
|
|
@@ -881,14 +881,16 @@ lutimes;
|
|
|
881
881
|
export async function realpath(path, options) {
|
|
882
882
|
path = normalizePath(path);
|
|
883
883
|
const { base, dir } = parse(path);
|
|
884
|
-
const lpath = join(dir == '/' ? '/' : await realpath(dir), base);
|
|
884
|
+
const lpath = join(dir == '/' ? '/' : await (cache.paths.get(dir) || realpath(dir)), base);
|
|
885
885
|
const { fs, path: resolvedPath, mountPoint } = resolveMount(lpath);
|
|
886
886
|
try {
|
|
887
|
-
const
|
|
888
|
-
|
|
887
|
+
const _stats = cache.stats.get(lpath) || fs.stat(resolvedPath);
|
|
888
|
+
cache.stats.set(lpath, _stats);
|
|
889
|
+
if (!(await _stats).isSymbolicLink()) {
|
|
889
890
|
return lpath;
|
|
890
891
|
}
|
|
891
|
-
|
|
892
|
+
const target = mountPoint + (await readlink(lpath));
|
|
893
|
+
return await (cache.paths.get(target) || realpath(target));
|
|
892
894
|
}
|
|
893
895
|
catch (e) {
|
|
894
896
|
if (e.code == 'ENOENT') {
|
|
@@ -943,17 +945,16 @@ access;
|
|
|
943
945
|
*/
|
|
944
946
|
export async function rm(path, options) {
|
|
945
947
|
path = normalizePath(path);
|
|
946
|
-
const
|
|
948
|
+
const stats = await (cache.stats.get(path) ||
|
|
947
949
|
stat(path).catch((error) => {
|
|
948
950
|
if (error.code == 'ENOENT' && options?.force)
|
|
949
951
|
return undefined;
|
|
950
952
|
throw error;
|
|
951
|
-
});
|
|
952
|
-
cache.setStats(path, _stats);
|
|
953
|
-
const stats = await _stats;
|
|
953
|
+
}));
|
|
954
954
|
if (!stats) {
|
|
955
955
|
return;
|
|
956
956
|
}
|
|
957
|
+
cache.stats.setSync(path, stats);
|
|
957
958
|
switch (stats.mode & constants.S_IFMT) {
|
|
958
959
|
case constants.S_IFDIR:
|
|
959
960
|
if (options?.recursive) {
|
|
@@ -972,11 +973,11 @@ export async function rm(path, options) {
|
|
|
972
973
|
case constants.S_IFIFO:
|
|
973
974
|
case constants.S_IFSOCK:
|
|
974
975
|
default:
|
|
975
|
-
cache.
|
|
976
|
+
cache.stats.clear();
|
|
976
977
|
throw new ErrnoError(Errno.EPERM, 'File type not supported', path, 'rm');
|
|
977
978
|
}
|
|
978
979
|
if (!options?._isIndirect) {
|
|
979
|
-
cache.
|
|
980
|
+
cache.stats.clear();
|
|
980
981
|
}
|
|
981
982
|
}
|
|
982
983
|
rm;
|
|
@@ -28,6 +28,12 @@ export declare function resolveMount(path: string): {
|
|
|
28
28
|
path: string;
|
|
29
29
|
mountPoint: string;
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Wait for all file systems to be ready and synced.
|
|
33
|
+
* May be removed at some point.
|
|
34
|
+
* @experimental @internal
|
|
35
|
+
*/
|
|
36
|
+
export declare function _synced(): Promise<void>;
|
|
31
37
|
/**
|
|
32
38
|
* Reverse maps the paths in text from the mounted FileSystem to the global path
|
|
33
39
|
* @hidden
|