@zenfs/core 2.2.3 → 2.3.1
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/backend.js +6 -9
- package/dist/backends/cow.js +4 -4
- package/dist/backends/fetch.js +8 -6
- package/dist/backends/memory.js +4 -2
- package/dist/backends/passthrough.js +2 -0
- package/dist/backends/port.d.ts +16 -89
- package/dist/backends/port.js +35 -171
- package/dist/backends/single_buffer.d.ts +2 -2
- package/dist/backends/single_buffer.js +165 -198
- package/dist/backends/store/fs.js +50 -73
- package/dist/backends/store/map.js +1 -2
- package/dist/backends/store/store.js +23 -27
- package/dist/config.js +2 -3
- package/dist/context.js +2 -2
- package/dist/internal/devices.js +7 -10
- package/dist/internal/file_index.js +3 -8
- package/dist/internal/filesystem.js +19 -12
- package/dist/internal/index_fs.js +3 -4
- package/dist/internal/inode.js +144 -187
- package/dist/internal/rpc.d.ts +143 -0
- package/dist/internal/rpc.js +251 -0
- package/dist/mixins/async.js +5 -6
- package/dist/mixins/mutexed.js +16 -10
- package/dist/path.js +3 -4
- package/dist/polyfills.js +51 -22
- package/dist/readline.js +32 -30
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +11 -5
- package/dist/vfs/acl.js +44 -68
- package/dist/vfs/async.js +4 -4
- package/dist/vfs/dir.js +12 -8
- package/dist/vfs/file.js +22 -18
- package/dist/vfs/ioctl.js +39 -62
- package/dist/vfs/promises.js +48 -39
- package/dist/vfs/shared.js +4 -5
- package/dist/vfs/stats.js +104 -77
- package/dist/vfs/streams.js +11 -8
- package/dist/vfs/sync.js +23 -26
- package/dist/vfs/watchers.js +9 -3
- package/dist/vfs/xattr.js +6 -12
- package/package.json +2 -2
- package/scripts/test.js +16 -7
- package/tests/backend/fetch.test.ts +14 -14
- package/tests/backend/port.test.ts +25 -17
- package/tests/common/handle.test.ts +5 -3
- package/tests/fetch/run.sh +2 -1
- package/tests/fs/scaling.test.ts +32 -0
- package/tests/fs/watch.test.ts +2 -5
- package/tests/setup/single-buffer.ts +1 -1
- package/tests/tsconfig.json +3 -2
- package/types/uint8array.d.ts +64 -0
|
@@ -70,12 +70,22 @@ import { WrappedTransaction } from './store.js';
|
|
|
70
70
|
* @internal
|
|
71
71
|
*/
|
|
72
72
|
export class StoreFS extends FileSystem {
|
|
73
|
+
store;
|
|
74
|
+
/**
|
|
75
|
+
* A map of paths to inode IDs
|
|
76
|
+
* @internal @hidden
|
|
77
|
+
*/
|
|
78
|
+
_ids = new Map([['/', 0]]);
|
|
79
|
+
/**
|
|
80
|
+
* A map of inode IDs to paths
|
|
81
|
+
* @internal @hidden
|
|
82
|
+
*/
|
|
83
|
+
_paths = new Map([[0, new Set('/')]]);
|
|
73
84
|
/**
|
|
74
85
|
* Gets the first path associated with an inode
|
|
75
86
|
*/
|
|
76
87
|
_path(id) {
|
|
77
|
-
|
|
78
|
-
const [path] = (_a = this._paths.get(id)) !== null && _a !== void 0 ? _a : [];
|
|
88
|
+
const [path] = this._paths.get(id) ?? [];
|
|
79
89
|
return path;
|
|
80
90
|
}
|
|
81
91
|
/**
|
|
@@ -91,8 +101,7 @@ export class StoreFS extends FileSystem {
|
|
|
91
101
|
* Remove a inode/path pair
|
|
92
102
|
*/
|
|
93
103
|
_remove(ino) {
|
|
94
|
-
|
|
95
|
-
for (const path of (_a = this._paths.get(ino)) !== null && _a !== void 0 ? _a : []) {
|
|
104
|
+
for (const path of this._paths.get(ino) ?? []) {
|
|
96
105
|
this._ids.delete(path);
|
|
97
106
|
}
|
|
98
107
|
this._paths.delete(ino);
|
|
@@ -123,6 +132,7 @@ export class StoreFS extends FileSystem {
|
|
|
123
132
|
p.add(newKey);
|
|
124
133
|
}
|
|
125
134
|
}
|
|
135
|
+
_initialized = false;
|
|
126
136
|
async ready() {
|
|
127
137
|
if (this._initialized)
|
|
128
138
|
return;
|
|
@@ -132,31 +142,18 @@ export class StoreFS extends FileSystem {
|
|
|
132
142
|
this._initialized = true;
|
|
133
143
|
}
|
|
134
144
|
constructor(store) {
|
|
135
|
-
|
|
136
|
-
super((_a = store.type) !== null && _a !== void 0 ? _a : 0x6b766673, store.name);
|
|
145
|
+
super(store.type ?? 0x6b766673, store.name);
|
|
137
146
|
this.store = store;
|
|
138
|
-
/**
|
|
139
|
-
* A map of paths to inode IDs
|
|
140
|
-
* @internal @hidden
|
|
141
|
-
*/
|
|
142
|
-
this._ids = new Map([['/', 0]]);
|
|
143
|
-
/**
|
|
144
|
-
* A map of inode IDs to paths
|
|
145
|
-
* @internal @hidden
|
|
146
|
-
*/
|
|
147
|
-
this._paths = new Map([[0, new Set('/')]]);
|
|
148
|
-
this._initialized = false;
|
|
149
147
|
store.fs = this;
|
|
150
|
-
this._uuid =
|
|
148
|
+
this._uuid = store.uuid ?? this.uuid;
|
|
151
149
|
this.label = store.label;
|
|
152
|
-
debug(this.name + ': supports features: ' +
|
|
150
|
+
debug(this.name + ': supports features: ' + this.store.flags?.join(', '));
|
|
153
151
|
}
|
|
154
152
|
/**
|
|
155
153
|
* @experimental
|
|
156
154
|
*/
|
|
157
155
|
usage() {
|
|
158
|
-
|
|
159
|
-
return (((_b = (_a = this.store).usage) === null || _b === void 0 ? void 0 : _b.call(_a)) || {
|
|
156
|
+
return (this.store.usage?.() || {
|
|
160
157
|
totalSpace: 0,
|
|
161
158
|
freeSpace: 0,
|
|
162
159
|
});
|
|
@@ -214,7 +211,6 @@ export class StoreFS extends FileSystem {
|
|
|
214
211
|
}
|
|
215
212
|
}
|
|
216
213
|
async createIndex() {
|
|
217
|
-
var _a;
|
|
218
214
|
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
219
215
|
try {
|
|
220
216
|
const index = new Index();
|
|
@@ -226,7 +222,7 @@ export class StoreFS extends FileSystem {
|
|
|
226
222
|
const inode = new Inode(await tx.get(ino));
|
|
227
223
|
index.set(path, inode);
|
|
228
224
|
if (inode.mode & S_IFDIR) {
|
|
229
|
-
const dir = decodeDirListing((
|
|
225
|
+
const dir = decodeDirListing((await tx.get(inode.data)) ?? _throw(withErrno('ENODATA')));
|
|
230
226
|
for (const [name, id] of Object.entries(dir)) {
|
|
231
227
|
queue.push([join(path, name), id]);
|
|
232
228
|
}
|
|
@@ -246,7 +242,6 @@ export class StoreFS extends FileSystem {
|
|
|
246
242
|
}
|
|
247
243
|
}
|
|
248
244
|
createIndexSync() {
|
|
249
|
-
var _a;
|
|
250
245
|
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
251
246
|
try {
|
|
252
247
|
const index = new Index();
|
|
@@ -258,7 +253,7 @@ export class StoreFS extends FileSystem {
|
|
|
258
253
|
const inode = new Inode(tx.getSync(ino));
|
|
259
254
|
index.set(path, inode);
|
|
260
255
|
if (inode.mode & S_IFDIR) {
|
|
261
|
-
const dir = decodeDirListing(
|
|
256
|
+
const dir = decodeDirListing(tx.getSync(inode.data) ?? _throw(withErrno('ENODATA')));
|
|
262
257
|
for (const [name, id] of Object.entries(dir)) {
|
|
263
258
|
queue.push([join(path, name), id]);
|
|
264
259
|
}
|
|
@@ -279,13 +274,12 @@ export class StoreFS extends FileSystem {
|
|
|
279
274
|
* @todo Make rename compatible with the cache.
|
|
280
275
|
*/
|
|
281
276
|
async rename(oldPath, newPath) {
|
|
282
|
-
var _a, _b, _c;
|
|
283
277
|
const env_5 = { stack: [], error: void 0, hasError: false };
|
|
284
278
|
try {
|
|
285
279
|
const tx = __addDisposableResource(env_5, this.transaction(), true);
|
|
286
280
|
const _old = parse(oldPath), _new = parse(newPath),
|
|
287
281
|
// Remove oldPath from parent's directory listing.
|
|
288
|
-
oldDirNode = await this.findInode(tx, _old.dir), oldDirList = decodeDirListing((
|
|
282
|
+
oldDirNode = await this.findInode(tx, _old.dir), oldDirList = decodeDirListing((await tx.get(oldDirNode.data)) ?? _throw(withErrno('ENODATA')));
|
|
289
283
|
if (!oldDirList[_old.base])
|
|
290
284
|
throw withErrno('ENOENT');
|
|
291
285
|
const ino = oldDirList[_old.base];
|
|
@@ -304,9 +298,9 @@ export class StoreFS extends FileSystem {
|
|
|
304
298
|
const newDirNode = sameParent ? oldDirNode : await this.findInode(tx, _new.dir);
|
|
305
299
|
const newDirList = sameParent
|
|
306
300
|
? oldDirList
|
|
307
|
-
: decodeDirListing((
|
|
301
|
+
: decodeDirListing((await tx.get(newDirNode.data)) ?? _throw(withErrno('ENODATA')));
|
|
308
302
|
if (newDirList[_new.base]) {
|
|
309
|
-
const existing = new Inode((
|
|
303
|
+
const existing = new Inode((await tx.get(newDirList[_new.base])) ?? _throw(withErrno('ENOENT')));
|
|
310
304
|
if (!existing.toStats().isFile())
|
|
311
305
|
throw withErrno('EISDIR');
|
|
312
306
|
await tx.remove(existing.data);
|
|
@@ -330,13 +324,12 @@ export class StoreFS extends FileSystem {
|
|
|
330
324
|
}
|
|
331
325
|
}
|
|
332
326
|
renameSync(oldPath, newPath) {
|
|
333
|
-
var _a, _b, _c;
|
|
334
327
|
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
335
328
|
try {
|
|
336
329
|
const tx = __addDisposableResource(env_6, this.transaction(), false);
|
|
337
330
|
const _old = parse(oldPath), _new = parse(newPath),
|
|
338
331
|
// Remove oldPath from parent's directory listing.
|
|
339
|
-
oldDirNode = this.findInodeSync(tx, _old.dir), oldDirList = decodeDirListing(
|
|
332
|
+
oldDirNode = this.findInodeSync(tx, _old.dir), oldDirList = decodeDirListing(tx.getSync(oldDirNode.data) ?? _throw(withErrno('ENODATA')));
|
|
340
333
|
if (!oldDirList[_old.base])
|
|
341
334
|
throw withErrno('ENOENT');
|
|
342
335
|
const ino = oldDirList[_old.base];
|
|
@@ -354,9 +347,9 @@ export class StoreFS extends FileSystem {
|
|
|
354
347
|
const sameParent = _new.dir === _old.dir;
|
|
355
348
|
// Prevent us from re-grabbing the same directory listing, which still contains `old_path.base.`
|
|
356
349
|
const newDirNode = sameParent ? oldDirNode : this.findInodeSync(tx, _new.dir);
|
|
357
|
-
const newDirList = sameParent ? oldDirList : decodeDirListing(
|
|
350
|
+
const newDirList = sameParent ? oldDirList : decodeDirListing(tx.getSync(newDirNode.data) ?? _throw(withErrno('ENODATA')));
|
|
358
351
|
if (newDirList[_new.base]) {
|
|
359
|
-
const existing = new Inode(
|
|
352
|
+
const existing = new Inode(tx.getSync(newDirList[_new.base]) ?? _throw(withErrno('ENOENT')));
|
|
360
353
|
if (!existing.toStats().isFile())
|
|
361
354
|
throw withErrno('EISDIR');
|
|
362
355
|
tx.removeSync(existing.data);
|
|
@@ -480,12 +473,11 @@ export class StoreFS extends FileSystem {
|
|
|
480
473
|
return this.commitNewSync(path, options, encodeUTF8('{}'));
|
|
481
474
|
}
|
|
482
475
|
async readdir(path) {
|
|
483
|
-
var _a;
|
|
484
476
|
const env_11 = { stack: [], error: void 0, hasError: false };
|
|
485
477
|
try {
|
|
486
478
|
const tx = __addDisposableResource(env_11, this.transaction(), true);
|
|
487
479
|
const node = await this.findInode(tx, path);
|
|
488
|
-
return Object.keys(decodeDirListing((
|
|
480
|
+
return Object.keys(decodeDirListing((await tx.get(node.data)) ?? _throw(withErrno('ENOENT'))));
|
|
489
481
|
}
|
|
490
482
|
catch (e_11) {
|
|
491
483
|
env_11.error = e_11;
|
|
@@ -498,12 +490,11 @@ export class StoreFS extends FileSystem {
|
|
|
498
490
|
}
|
|
499
491
|
}
|
|
500
492
|
readdirSync(path) {
|
|
501
|
-
var _a;
|
|
502
493
|
const env_12 = { stack: [], error: void 0, hasError: false };
|
|
503
494
|
try {
|
|
504
495
|
const tx = __addDisposableResource(env_12, this.transaction(), false);
|
|
505
496
|
const node = this.findInodeSync(tx, path);
|
|
506
|
-
return Object.keys(decodeDirListing(
|
|
497
|
+
return Object.keys(decodeDirListing(tx.getSync(node.data) ?? _throw(withErrno('ENOENT'))));
|
|
507
498
|
}
|
|
508
499
|
catch (e_12) {
|
|
509
500
|
env_12.error = e_12;
|
|
@@ -522,11 +513,10 @@ export class StoreFS extends FileSystem {
|
|
|
522
513
|
*/
|
|
523
514
|
syncSync() { }
|
|
524
515
|
async link(target, link) {
|
|
525
|
-
var _a;
|
|
526
516
|
const env_13 = { stack: [], error: void 0, hasError: false };
|
|
527
517
|
try {
|
|
528
518
|
const tx = __addDisposableResource(env_13, this.transaction(), true);
|
|
529
|
-
const newDir = dirname(link), newDirNode = await this.findInode(tx, newDir), listing = decodeDirListing((
|
|
519
|
+
const newDir = dirname(link), newDirNode = await this.findInode(tx, newDir), listing = decodeDirListing((await tx.get(newDirNode.data)) ?? _throw(withErrno('ENOENT')));
|
|
530
520
|
const inode = await this.findInode(tx, target);
|
|
531
521
|
inode.nlink++;
|
|
532
522
|
listing[basename(link)] = inode.ino;
|
|
@@ -546,11 +536,10 @@ export class StoreFS extends FileSystem {
|
|
|
546
536
|
}
|
|
547
537
|
}
|
|
548
538
|
linkSync(target, link) {
|
|
549
|
-
var _a;
|
|
550
539
|
const env_14 = { stack: [], error: void 0, hasError: false };
|
|
551
540
|
try {
|
|
552
541
|
const tx = __addDisposableResource(env_14, this.transaction(), false);
|
|
553
|
-
const newDir = dirname(link), newDirNode = this.findInodeSync(tx, newDir), listing = decodeDirListing(
|
|
542
|
+
const newDir = dirname(link), newDirNode = this.findInodeSync(tx, newDir), listing = decodeDirListing(tx.getSync(newDirNode.data) ?? _throw(withErrno('ENOENT')));
|
|
554
543
|
const inode = this.findInodeSync(tx, target);
|
|
555
544
|
inode.nlink++;
|
|
556
545
|
listing[basename(link)] = inode.ino;
|
|
@@ -568,14 +557,13 @@ export class StoreFS extends FileSystem {
|
|
|
568
557
|
}
|
|
569
558
|
}
|
|
570
559
|
async read(path, buffer, offset, end) {
|
|
571
|
-
var _a;
|
|
572
560
|
const env_15 = { stack: [], error: void 0, hasError: false };
|
|
573
561
|
try {
|
|
574
562
|
const tx = __addDisposableResource(env_15, this.transaction(), true);
|
|
575
563
|
const inode = await this.findInode(tx, path);
|
|
576
564
|
if (inode.size == 0)
|
|
577
565
|
return;
|
|
578
|
-
const data = (
|
|
566
|
+
const data = (await tx.get(inode.data, offset, end)) ?? _throw(withErrno('ENODATA'));
|
|
579
567
|
const _ = tx.flag('partial') ? data : data.subarray(offset, end);
|
|
580
568
|
if (_.byteLength > buffer.byteLength)
|
|
581
569
|
err(`Trying to place ${_.byteLength} bytes into a ${buffer.byteLength} byte buffer on read`);
|
|
@@ -592,14 +580,13 @@ export class StoreFS extends FileSystem {
|
|
|
592
580
|
}
|
|
593
581
|
}
|
|
594
582
|
readSync(path, buffer, offset, end) {
|
|
595
|
-
var _a;
|
|
596
583
|
const env_16 = { stack: [], error: void 0, hasError: false };
|
|
597
584
|
try {
|
|
598
585
|
const tx = __addDisposableResource(env_16, this.transaction(), false);
|
|
599
586
|
const inode = this.findInodeSync(tx, path);
|
|
600
587
|
if (inode.size == 0)
|
|
601
588
|
return;
|
|
602
|
-
const data =
|
|
589
|
+
const data = tx.getSync(inode.data, offset, end) ?? _throw(withErrno('ENODATA'));
|
|
603
590
|
const _ = tx.flag('partial') ? data : data.subarray(offset, end);
|
|
604
591
|
if (_.byteLength > buffer.byteLength)
|
|
605
592
|
err(`Trying to place ${_.byteLength} bytes into a ${buffer.byteLength} byte buffer on read`);
|
|
@@ -614,14 +601,13 @@ export class StoreFS extends FileSystem {
|
|
|
614
601
|
}
|
|
615
602
|
}
|
|
616
603
|
async write(path, data, offset) {
|
|
617
|
-
var _a;
|
|
618
604
|
const env_17 = { stack: [], error: void 0, hasError: false };
|
|
619
605
|
try {
|
|
620
606
|
const tx = __addDisposableResource(env_17, this.transaction(), true);
|
|
621
607
|
const inode = await this.findInode(tx, path);
|
|
622
608
|
let buffer = data;
|
|
623
609
|
if (!tx.flag('partial')) {
|
|
624
|
-
buffer = extendBuffer((
|
|
610
|
+
buffer = extendBuffer((await tx.get(inode.data)) ?? new Uint8Array(), offset + data.byteLength);
|
|
625
611
|
buffer.set(data, offset);
|
|
626
612
|
offset = 0;
|
|
627
613
|
}
|
|
@@ -640,14 +626,13 @@ export class StoreFS extends FileSystem {
|
|
|
640
626
|
}
|
|
641
627
|
}
|
|
642
628
|
writeSync(path, data, offset) {
|
|
643
|
-
var _a;
|
|
644
629
|
const env_18 = { stack: [], error: void 0, hasError: false };
|
|
645
630
|
try {
|
|
646
631
|
const tx = __addDisposableResource(env_18, this.transaction(), false);
|
|
647
632
|
const inode = this.findInodeSync(tx, path);
|
|
648
633
|
let buffer = data;
|
|
649
634
|
if (!tx.flag('partial')) {
|
|
650
|
-
buffer = extendBuffer(
|
|
635
|
+
buffer = extendBuffer(tx.getSync(inode.data) ?? new Uint8Array(), offset + data.byteLength);
|
|
651
636
|
buffer.set(data, offset);
|
|
652
637
|
offset = 0;
|
|
653
638
|
}
|
|
@@ -797,35 +782,33 @@ export class StoreFS extends FileSystem {
|
|
|
797
782
|
* Find an inode without using the ID tables
|
|
798
783
|
*/
|
|
799
784
|
async _findInode(tx, path, visited = new Set()) {
|
|
800
|
-
var _a, _b, _c;
|
|
801
785
|
if (visited.has(path))
|
|
802
786
|
throw crit(withErrno('EIO', 'Infinite loop detected while finding inode'));
|
|
803
787
|
visited.add(path);
|
|
804
788
|
if (path == '/')
|
|
805
|
-
return new Inode((
|
|
789
|
+
return new Inode((await tx.get(rootIno)) ?? _throw(withErrno('ENODATA')));
|
|
806
790
|
const { dir: parent, base: filename } = parse(path);
|
|
807
791
|
const inode = await this._findInode(tx, parent, visited);
|
|
808
|
-
const dirList = decodeDirListing((
|
|
792
|
+
const dirList = decodeDirListing((await tx.get(inode.data)) ?? _throw(withErrno('ENODATA')));
|
|
809
793
|
if (!(filename in dirList))
|
|
810
794
|
throw withErrno('ENOENT');
|
|
811
|
-
return new Inode((
|
|
795
|
+
return new Inode((await tx.get(dirList[filename])) ?? _throw(withErrno('ENODATA')));
|
|
812
796
|
}
|
|
813
797
|
/**
|
|
814
798
|
* Find an inode without using the ID tables
|
|
815
799
|
*/
|
|
816
800
|
_findInodeSync(tx, path, visited = new Set()) {
|
|
817
|
-
var _a, _b, _c;
|
|
818
801
|
if (visited.has(path))
|
|
819
802
|
throw crit(withErrno('EIO', 'Infinite loop detected while finding inode'));
|
|
820
803
|
visited.add(path);
|
|
821
804
|
if (path == '/')
|
|
822
|
-
return new Inode(
|
|
805
|
+
return new Inode(tx.getSync(rootIno) ?? _throw(withErrno('ENOENT')));
|
|
823
806
|
const { dir: parent, base: filename } = parse(path);
|
|
824
807
|
const inode = this._findInodeSync(tx, parent, visited);
|
|
825
|
-
const dir = decodeDirListing(
|
|
808
|
+
const dir = decodeDirListing(tx.getSync(inode.data) ?? _throw(withErrno('ENODATA')));
|
|
826
809
|
if (!(filename in dir))
|
|
827
810
|
throw withErrno('ENOENT');
|
|
828
|
-
return new Inode(
|
|
811
|
+
return new Inode(tx.getSync(dir[filename]) ?? _throw(withErrno('ENODATA')));
|
|
829
812
|
}
|
|
830
813
|
/**
|
|
831
814
|
* Finds the Inode of `path`.
|
|
@@ -833,13 +816,12 @@ export class StoreFS extends FileSystem {
|
|
|
833
816
|
* @todo memoize/cache
|
|
834
817
|
*/
|
|
835
818
|
async findInode(tx, path) {
|
|
836
|
-
var _a;
|
|
837
819
|
if (this.attributes.has('no_id_tables'))
|
|
838
820
|
return await this._findInode(tx, path);
|
|
839
821
|
const ino = this._ids.get(path);
|
|
840
822
|
if (ino === undefined)
|
|
841
823
|
throw withErrno('ENOENT');
|
|
842
|
-
return new Inode((
|
|
824
|
+
return new Inode((await tx.get(ino)) ?? _throw(withErrno('ENOENT')));
|
|
843
825
|
}
|
|
844
826
|
/**
|
|
845
827
|
* Finds the Inode of `path`.
|
|
@@ -848,18 +830,17 @@ export class StoreFS extends FileSystem {
|
|
|
848
830
|
* @todo memoize/cache
|
|
849
831
|
*/
|
|
850
832
|
findInodeSync(tx, path) {
|
|
851
|
-
var _a;
|
|
852
833
|
if (this.attributes.has('no_id_tables'))
|
|
853
834
|
return this._findInodeSync(tx, path);
|
|
854
835
|
const ino = this._ids.get(path);
|
|
855
836
|
if (ino === undefined)
|
|
856
837
|
throw withErrno('ENOENT');
|
|
857
|
-
return new Inode(
|
|
838
|
+
return new Inode(tx.getSync(ino) ?? _throw(withErrno('ENOENT')));
|
|
858
839
|
}
|
|
840
|
+
_lastID;
|
|
859
841
|
/** Allocates a new ID and adds the ID/path */
|
|
860
842
|
allocNew(path) {
|
|
861
|
-
|
|
862
|
-
(_a = this._lastID) !== null && _a !== void 0 ? _a : (this._lastID = Math.max(...this._paths.keys()));
|
|
843
|
+
this._lastID ??= Math.max(...this._paths.keys());
|
|
863
844
|
this._lastID += 2;
|
|
864
845
|
const id = this._lastID;
|
|
865
846
|
if (id > size_max)
|
|
@@ -875,7 +856,6 @@ export class StoreFS extends FileSystem {
|
|
|
875
856
|
* @param data The data to store at the file's data node.
|
|
876
857
|
*/
|
|
877
858
|
async commitNew(path, options, data) {
|
|
878
|
-
var _a;
|
|
879
859
|
const env_22 = { stack: [], error: void 0, hasError: false };
|
|
880
860
|
try {
|
|
881
861
|
/*
|
|
@@ -888,7 +868,7 @@ export class StoreFS extends FileSystem {
|
|
|
888
868
|
const tx = __addDisposableResource(env_22, this.transaction(), true);
|
|
889
869
|
const { dir: parentPath, base: fname } = parse(path);
|
|
890
870
|
const parent = await this.findInode(tx, parentPath);
|
|
891
|
-
const listing = decodeDirListing((
|
|
871
|
+
const listing = decodeDirListing((await tx.get(parent.data)) ?? _throw(withErrno('ENOENT')));
|
|
892
872
|
// Check if file already exists.
|
|
893
873
|
if (listing[fname])
|
|
894
874
|
throw withErrno('EEXIST');
|
|
@@ -928,7 +908,6 @@ export class StoreFS extends FileSystem {
|
|
|
928
908
|
* @return The Inode for the new file.
|
|
929
909
|
*/
|
|
930
910
|
commitNewSync(path, options, data) {
|
|
931
|
-
var _a;
|
|
932
911
|
const env_23 = { stack: [], error: void 0, hasError: false };
|
|
933
912
|
try {
|
|
934
913
|
/*
|
|
@@ -941,7 +920,7 @@ export class StoreFS extends FileSystem {
|
|
|
941
920
|
const tx = __addDisposableResource(env_23, this.transaction(), false);
|
|
942
921
|
const { dir: parentPath, base: fname } = parse(path);
|
|
943
922
|
const parent = this.findInodeSync(tx, parentPath);
|
|
944
|
-
const listing = decodeDirListing(
|
|
923
|
+
const listing = decodeDirListing(tx.getSync(parent.data) ?? _throw(withErrno('ENOENT')));
|
|
945
924
|
if (listing[fname])
|
|
946
925
|
throw withErrno('EEXIST');
|
|
947
926
|
const id = this.allocNew(path);
|
|
@@ -974,15 +953,14 @@ export class StoreFS extends FileSystem {
|
|
|
974
953
|
* @param isDir Does the path belong to a directory, or a file?
|
|
975
954
|
*/
|
|
976
955
|
async remove(path, isDir) {
|
|
977
|
-
var _a, _b;
|
|
978
956
|
const env_24 = { stack: [], error: void 0, hasError: false };
|
|
979
957
|
try {
|
|
980
958
|
const tx = __addDisposableResource(env_24, this.transaction(), true);
|
|
981
|
-
const { dir: parent, base: fileName } = parse(path), parentNode = await this.findInode(tx, parent), listing = decodeDirListing((
|
|
959
|
+
const { dir: parent, base: fileName } = parse(path), parentNode = await this.findInode(tx, parent), listing = decodeDirListing((await tx.get(parentNode.data)) ?? _throw(withErrno('ENOENT')));
|
|
982
960
|
if (!listing[fileName])
|
|
983
961
|
throw withErrno('ENOENT');
|
|
984
962
|
const ino = listing[fileName];
|
|
985
|
-
const inode = new Inode((
|
|
963
|
+
const inode = new Inode((await tx.get(ino)) ?? _throw(withErrno('ENOENT')));
|
|
986
964
|
delete listing[fileName];
|
|
987
965
|
if (!isDir && isDirectory(inode))
|
|
988
966
|
throw withErrno('EISDIR');
|
|
@@ -1014,14 +992,13 @@ export class StoreFS extends FileSystem {
|
|
|
1014
992
|
* @param isDir Does the path belong to a directory, or a file?
|
|
1015
993
|
*/
|
|
1016
994
|
removeSync(path, isDir) {
|
|
1017
|
-
var _a, _b;
|
|
1018
995
|
const env_25 = { stack: [], error: void 0, hasError: false };
|
|
1019
996
|
try {
|
|
1020
997
|
const tx = __addDisposableResource(env_25, this.transaction(), false);
|
|
1021
|
-
const { dir: parent, base: fileName } = parse(path), parentNode = this.findInodeSync(tx, parent), listing = decodeDirListing(
|
|
998
|
+
const { dir: parent, base: fileName } = parse(path), parentNode = this.findInodeSync(tx, parent), listing = decodeDirListing(tx.getSync(parentNode.data) ?? _throw(withErrno('ENOENT'))), ino = listing[fileName];
|
|
1022
999
|
if (!ino)
|
|
1023
1000
|
throw withErrno('ENOENT');
|
|
1024
|
-
const inode = new Inode(
|
|
1001
|
+
const inode = new Inode(tx.getSync(ino) ?? _throw(withErrno('ENOENT')));
|
|
1025
1002
|
delete listing[fileName];
|
|
1026
1003
|
if (!isDir && isDirectory(inode))
|
|
1027
1004
|
throw withErrno('EISDIR');
|
|
@@ -10,8 +10,7 @@ export class SyncMapTransaction extends SyncTransaction {
|
|
|
10
10
|
return this.store.keys();
|
|
11
11
|
}
|
|
12
12
|
async get(id) {
|
|
13
|
-
|
|
14
|
-
return await ((_c = (_b = (_a = this.store).getAsync) === null || _b === void 0 ? void 0 : _b.call(_a, id)) !== null && _c !== void 0 ? _c : this.store.get(id));
|
|
13
|
+
return await (this.store.getAsync?.(id) ?? this.store.get(id));
|
|
15
14
|
}
|
|
16
15
|
getSync(id) {
|
|
17
16
|
return this.store.get(id);
|
|
@@ -7,6 +7,7 @@ import '../../polyfills.js';
|
|
|
7
7
|
* @category Stores and Transactions
|
|
8
8
|
*/
|
|
9
9
|
export class Transaction {
|
|
10
|
+
store;
|
|
10
11
|
constructor(store) {
|
|
11
12
|
this.store = store;
|
|
12
13
|
}
|
|
@@ -34,10 +35,7 @@ export class SyncTransaction extends Transaction {
|
|
|
34
35
|
* @category Stores and Transactions
|
|
35
36
|
*/
|
|
36
37
|
export class AsyncTransaction extends Transaction {
|
|
37
|
-
|
|
38
|
-
super(...arguments);
|
|
39
|
-
this.asyncDone = Promise.resolve();
|
|
40
|
-
}
|
|
38
|
+
asyncDone = Promise.resolve();
|
|
41
39
|
/**
|
|
42
40
|
* Run a asynchronous operation from a sync context. Not magic and subject to (race) conditions.
|
|
43
41
|
* @internal
|
|
@@ -51,9 +49,7 @@ export class AsyncTransaction extends Transaction {
|
|
|
51
49
|
* @internal
|
|
52
50
|
*/
|
|
53
51
|
_cached(id, info) {
|
|
54
|
-
|
|
55
|
-
var _b;
|
|
56
|
-
(_a = (_b = this.store).cache) !== null && _a !== void 0 ? _a : (_b.cache = new Map());
|
|
52
|
+
this.store.cache ??= new Map();
|
|
57
53
|
const resource = this.store.cache.get(id);
|
|
58
54
|
if (!resource)
|
|
59
55
|
return !info ? undefined : new Resource(id, info.size, {}, this.store.cache);
|
|
@@ -65,7 +61,7 @@ export class AsyncTransaction extends Transaction {
|
|
|
65
61
|
const resource = this._cached(id);
|
|
66
62
|
if (!resource)
|
|
67
63
|
return;
|
|
68
|
-
end
|
|
64
|
+
end ??= resource.size;
|
|
69
65
|
const missing = resource.missing(offset, end);
|
|
70
66
|
for (const { start, end } of missing) {
|
|
71
67
|
this.async(this.get(id, start, end));
|
|
@@ -83,9 +79,8 @@ export class AsyncTransaction extends Transaction {
|
|
|
83
79
|
this.async(this.set(id, data, offset));
|
|
84
80
|
}
|
|
85
81
|
removeSync(id) {
|
|
86
|
-
var _a;
|
|
87
82
|
this.async(this.remove(id));
|
|
88
|
-
|
|
83
|
+
this.store.cache?.delete(id);
|
|
89
84
|
}
|
|
90
85
|
}
|
|
91
86
|
/**
|
|
@@ -95,27 +90,28 @@ export class AsyncTransaction extends Transaction {
|
|
|
95
90
|
* @internal @hidden
|
|
96
91
|
*/
|
|
97
92
|
export class WrappedTransaction {
|
|
93
|
+
raw;
|
|
94
|
+
fs;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the transaction was committed or aborted
|
|
97
|
+
*/
|
|
98
|
+
done = false;
|
|
98
99
|
flag(flag) {
|
|
99
|
-
|
|
100
|
-
return (_b = (_a = this.raw.store.flags) === null || _a === void 0 ? void 0 : _a.includes(flag)) !== null && _b !== void 0 ? _b : false;
|
|
100
|
+
return this.raw.store.flags?.includes(flag) ?? false;
|
|
101
101
|
}
|
|
102
102
|
constructor(raw, fs) {
|
|
103
103
|
this.raw = raw;
|
|
104
104
|
this.fs = fs;
|
|
105
|
-
/**
|
|
106
|
-
* Whether the transaction was committed or aborted
|
|
107
|
-
*/
|
|
108
|
-
this.done = false;
|
|
109
|
-
/**
|
|
110
|
-
* Stores data in the keys we modify prior to modifying them.
|
|
111
|
-
* Allows us to roll back commits.
|
|
112
|
-
*/
|
|
113
|
-
this.originalData = new Map();
|
|
114
|
-
/**TransactionEntry
|
|
115
|
-
* List of keys modified in this transaction, if any.
|
|
116
|
-
*/
|
|
117
|
-
this.modifiedKeys = new Set();
|
|
118
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Stores data in the keys we modify prior to modifying them.
|
|
108
|
+
* Allows us to roll back commits.
|
|
109
|
+
*/
|
|
110
|
+
originalData = new Map();
|
|
111
|
+
/**TransactionEntry
|
|
112
|
+
* List of keys modified in this transaction, if any.
|
|
113
|
+
*/
|
|
114
|
+
modifiedKeys = new Set();
|
|
119
115
|
keys() {
|
|
120
116
|
return this.raw.keys();
|
|
121
117
|
}
|
|
@@ -234,7 +230,7 @@ export class WrappedTransaction {
|
|
|
234
230
|
const resource = tx._cached(id);
|
|
235
231
|
if (!resource)
|
|
236
232
|
throw e;
|
|
237
|
-
for (const range of resource.cached(offset, end
|
|
233
|
+
for (const range of resource.cached(offset, end ?? offset)) {
|
|
238
234
|
this.stash(id, await this.raw.get(id, range.start, range.end), range.start);
|
|
239
235
|
}
|
|
240
236
|
}
|
|
@@ -260,7 +256,7 @@ export class WrappedTransaction {
|
|
|
260
256
|
const resource = tx._cached(id);
|
|
261
257
|
if (!resource)
|
|
262
258
|
throw e;
|
|
263
|
-
for (const range of resource.cached(offset, end
|
|
259
|
+
for (const range of resource.cached(offset, end ?? offset)) {
|
|
264
260
|
this.stash(id, this.raw.getSync(id, range.start, range.end), range.start);
|
|
265
261
|
}
|
|
266
262
|
}
|
package/dist/config.js
CHANGED
|
@@ -107,7 +107,6 @@ export function addDevice(driver, options) {
|
|
|
107
107
|
* @see Configuration
|
|
108
108
|
*/
|
|
109
109
|
export async function configure(configuration) {
|
|
110
|
-
var _a, _b;
|
|
111
110
|
Object.assign(defaultContext.credentials, createCredentials({
|
|
112
111
|
uid: configuration.uid || 0,
|
|
113
112
|
gid: configuration.gid || 0,
|
|
@@ -120,8 +119,8 @@ export async function configure(configuration) {
|
|
|
120
119
|
for (const [_point, mountConfig] of Object.entries(configuration.mounts).sort(([a], [b]) => (a.length > b.length ? 1 : -1))) {
|
|
121
120
|
const point = _point.startsWith('/') ? _point : '/' + _point;
|
|
122
121
|
if (isBackendConfig(mountConfig)) {
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
mountConfig.disableAsyncCache ??= configuration.disableAsyncCache || false;
|
|
123
|
+
mountConfig.caseFold ??= configuration.caseFold;
|
|
125
124
|
}
|
|
126
125
|
if (point == '/')
|
|
127
126
|
fs.umount('/');
|
package/dist/context.js
CHANGED
|
@@ -16,8 +16,8 @@ export const boundContexts = new Map();
|
|
|
16
16
|
* Note that the default credentials of a bound context are copied from the global credentials.
|
|
17
17
|
* @category Contexts
|
|
18
18
|
*/
|
|
19
|
-
export function bindContext({ root =
|
|
20
|
-
const parent = this
|
|
19
|
+
export function bindContext({ root = this?.root || '/', pwd = this?.pwd || '/', credentials = structuredClone(defaultContext.credentials) } = {}) {
|
|
20
|
+
const parent = this ?? defaultContext;
|
|
21
21
|
const ctx = {
|
|
22
22
|
id: _nextId++,
|
|
23
23
|
root,
|
package/dist/internal/devices.js
CHANGED
|
@@ -14,6 +14,7 @@ import { Inode } from './inode.js';
|
|
|
14
14
|
* @category Internals
|
|
15
15
|
*/
|
|
16
16
|
export class DeviceFS extends StoreFS {
|
|
17
|
+
devices = new Map();
|
|
17
18
|
devicesWithDriver(driver, forceIdentity) {
|
|
18
19
|
if (forceIdentity && typeof driver == 'string') {
|
|
19
20
|
throw err(withErrno('EINVAL', 'Can not fetch devices using only a driver name'));
|
|
@@ -32,21 +33,20 @@ export class DeviceFS extends StoreFS {
|
|
|
32
33
|
* @internal
|
|
33
34
|
*/
|
|
34
35
|
_createDevice(driver, options = {}) {
|
|
35
|
-
var _a;
|
|
36
36
|
let ino = 1;
|
|
37
37
|
const lastDev = Array.from(this.devices.values()).at(-1);
|
|
38
|
-
while (this.store.has(ino) ||
|
|
38
|
+
while (this.store.has(ino) || lastDev?.inode.ino == ino)
|
|
39
39
|
ino++;
|
|
40
|
-
const init =
|
|
40
|
+
const init = driver.init?.(ino, options);
|
|
41
41
|
const dev = {
|
|
42
42
|
data: {},
|
|
43
43
|
minor: 0,
|
|
44
44
|
major: 0,
|
|
45
|
-
...omit(init
|
|
45
|
+
...omit(init ?? {}, 'metadata'),
|
|
46
46
|
driver,
|
|
47
47
|
inode: new Inode({
|
|
48
48
|
mode: S_IFCHR | 0o666,
|
|
49
|
-
...init
|
|
49
|
+
...init?.metadata,
|
|
50
50
|
}),
|
|
51
51
|
};
|
|
52
52
|
const path = '/' + (dev.name || driver.name) + (driver.singleton ? '' : this.devicesWithDriver(driver).length);
|
|
@@ -71,7 +71,6 @@ export class DeviceFS extends StoreFS {
|
|
|
71
71
|
// Please don't store your temporary files in /dev.
|
|
72
72
|
// If you do, you'll have up to 16 MiB
|
|
73
73
|
super(new InMemoryStore(0x1000000, 'devfs'));
|
|
74
|
-
this.devices = new Map();
|
|
75
74
|
}
|
|
76
75
|
async rename(oldPath, newPath) {
|
|
77
76
|
if (this.devices.has(oldPath))
|
|
@@ -182,16 +181,14 @@ export class DeviceFS extends StoreFS {
|
|
|
182
181
|
return super.linkSync(target, link);
|
|
183
182
|
}
|
|
184
183
|
async sync() {
|
|
185
|
-
var _a, _b;
|
|
186
184
|
for (const device of this.devices.values()) {
|
|
187
|
-
|
|
185
|
+
device.driver.sync?.(device);
|
|
188
186
|
}
|
|
189
187
|
return super.sync();
|
|
190
188
|
}
|
|
191
189
|
syncSync() {
|
|
192
|
-
var _a, _b;
|
|
193
190
|
for (const device of this.devices.values()) {
|
|
194
|
-
|
|
191
|
+
device.driver.sync?.(device);
|
|
195
192
|
}
|
|
196
193
|
return super.syncSync();
|
|
197
194
|
}
|