@zenfs/core 2.5.7 → 2.6.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/cow.d.ts +13 -0
- package/dist/backends/cow.js +48 -11
- package/dist/backends/single_buffer.d.ts +2 -2
- package/dist/backends/store/fs.d.ts +6 -6
- package/dist/backends/store/fs.js +14 -10
- package/dist/internal/devices.d.ts +6 -6
- package/dist/internal/filesystem.d.ts +4 -4
- package/dist/internal/index_fs.d.ts +4 -4
- package/dist/internal/index_fs.js +6 -8
- package/dist/internal/inode.js +3 -0
- package/dist/node/async.js +1 -1
- package/dist/node/dir.d.ts +3 -1
- package/dist/node/dir.js +23 -5
- package/dist/node/promises.d.ts +4 -2
- package/dist/node/promises.js +130 -89
- package/dist/node/streams.d.ts +4 -0
- package/dist/node/streams.js +9 -10
- package/dist/node/sync.js +71 -40
- package/dist/utils.d.ts +8 -1
- package/dist/utils.js +26 -7
- package/dist/vfs/async.js +224 -85
- package/dist/vfs/file.d.ts +13 -7
- package/dist/vfs/file.js +661 -357
- package/dist/vfs/shared.d.ts +1 -0
- package/dist/vfs/shared.js +19 -3
- package/dist/vfs/sync.js +214 -85
- package/dist/vfs/vcache.d.ts +66 -0
- package/dist/vfs/vcache.js +249 -0
- package/dist/vfs/vnode.d.ts +66 -0
- package/dist/vfs/vnode.js +200 -0
- package/dist/vfs/watchers.js +4 -2
- package/dist/vfs/xattr.js +2 -2
- package/eslint.shared.js +1 -1
- package/package.json +6 -3
- package/scripts/make-index.js +7 -1
- package/scripts/test.js +28 -21
- package/tests/backend/port.test.ts +3 -3
- package/tests/backend/store.test.ts +49 -0
- package/tests/common/inode.test.ts +8 -0
- package/tests/common.ts +62 -0
- package/tests/fetch/fetch.ts +6 -0
- package/tests/fetch/run.sh +2 -2
- package/tests/fetch/server.js +3 -3
- package/tests/fs/append.test.ts +5 -5
- package/tests/fs/concurrency.test.ts +52 -0
- package/tests/fs/dir.test.ts +13 -15
- package/tests/fs/directory.test.ts +32 -31
- package/tests/fs/errors.test.ts +151 -31
- package/tests/fs/exists.test.ts +4 -4
- package/tests/fs/links.test.ts +4 -11
- package/tests/fs/open.test.ts +4 -4
- package/tests/fs/permissions.test.ts +15 -15
- package/tests/fs/read.test.ts +9 -9
- package/tests/fs/readFile.test.ts +9 -9
- package/tests/fs/rename.test.ts +8 -8
- package/tests/fs/scaling.test.ts +4 -4
- package/tests/fs/stat.test.ts +20 -20
- package/tests/fs/streams.test.ts +9 -6
- package/tests/fs/tempdir.test.ts +33 -10
- package/tests/fs/times.test.ts +11 -11
- package/tests/fs/truncate.test.ts +6 -6
- package/tests/fs/watch.test.ts +107 -53
- package/tests/fs/write.test.ts +10 -10
- package/tests/fs/xattr.test.ts +3 -3
- package/tests/native/run.sh +3 -0
- package/tests/native/setup.ts +230 -0
- package/types/readable-stream.d.ts +2 -2
package/dist/node/sync.js
CHANGED
|
@@ -56,13 +56,14 @@ import { encodeUTF8 } from 'utilium';
|
|
|
56
56
|
import * as constants from '../constants.js';
|
|
57
57
|
import { wrap } from '../internal/error.js';
|
|
58
58
|
import { hasAccess, isDirectory } from '../internal/inode.js';
|
|
59
|
-
import { join, matchesGlob } from '../path.js';
|
|
59
|
+
import { dirname, join, matchesGlob } from '../path.js';
|
|
60
60
|
import { _tempDirName, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
|
|
61
61
|
import { checkAccess } from '../vfs/config.js';
|
|
62
62
|
import { deleteFD, fromFD, toFD } from '../vfs/file.js';
|
|
63
63
|
import * as flags from '../vfs/flags.js';
|
|
64
64
|
import { _statfs, resolveMount } from '../vfs/shared.js';
|
|
65
65
|
import * as _sync from '../vfs/sync.js';
|
|
66
|
+
import { cacheOf, lockPathSync } from '../vfs/vcache.js';
|
|
66
67
|
import { emitChange } from '../vfs/watchers.js';
|
|
67
68
|
import { Dir, Dirent } from './dir.js';
|
|
68
69
|
import { BigIntStats, Stats } from './stats.js';
|
|
@@ -118,13 +119,25 @@ export function unlinkSync(path) {
|
|
|
118
119
|
path = normalizePath(path);
|
|
119
120
|
const { fs, path: resolved } = resolveMount(path, this);
|
|
120
121
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
123
|
+
try {
|
|
124
|
+
if (checkAccess && !hasAccess(this, fs.statSync(resolved), constants.W_OK)) {
|
|
125
|
+
throw UV('EACCES', 'unlink');
|
|
126
|
+
}
|
|
127
|
+
const _ = __addDisposableResource(env_2, lockPathSync(fs, dirname(resolved), 'rw'), false);
|
|
128
|
+
fs.unlinkSync(resolved);
|
|
129
|
+
cacheOf(fs).remove(resolved);
|
|
130
|
+
}
|
|
131
|
+
catch (e_2) {
|
|
132
|
+
env_2.error = e_2;
|
|
133
|
+
env_2.hasError = true;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
__disposeResources(env_2);
|
|
123
137
|
}
|
|
124
|
-
fs.unlinkSync(resolved);
|
|
125
138
|
}
|
|
126
139
|
catch (e) {
|
|
127
|
-
throw setUVMessage(Object.assign(e, { path }));
|
|
140
|
+
throw setUVMessage(Object.assign(e, { syscall: 'unlink', path }));
|
|
128
141
|
}
|
|
129
142
|
emitChange(this, 'rename', path.toString());
|
|
130
143
|
}
|
|
@@ -146,13 +159,13 @@ export function lopenSync(path, flag, mode) {
|
|
|
146
159
|
return toFD(_sync.open.call(this, path, { flag, mode, preserveSymlinks: true }));
|
|
147
160
|
}
|
|
148
161
|
export function readFileSync(path, _options = {}) {
|
|
149
|
-
const
|
|
162
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
150
163
|
try {
|
|
151
164
|
const options = normalizeOptions(_options, null, 'r', 0o644);
|
|
152
165
|
const flag = flags.parse(options.flag);
|
|
153
166
|
if (flag & constants.O_WRONLY)
|
|
154
167
|
throw UV('EBADF', 'read', path.toString());
|
|
155
|
-
const file = __addDisposableResource(
|
|
168
|
+
const file = __addDisposableResource(env_3, typeof path == 'number'
|
|
156
169
|
? fromFD(this, path)
|
|
157
170
|
: _sync.open.call(this, path.toString(), { flag: options.flag, mode: 0o644, preserveSymlinks: false }), false);
|
|
158
171
|
const { size } = file.stat();
|
|
@@ -160,17 +173,17 @@ export function readFileSync(path, _options = {}) {
|
|
|
160
173
|
file.readSync(data, 0, size, 0);
|
|
161
174
|
return options.encoding ? data.toString(options.encoding) : data;
|
|
162
175
|
}
|
|
163
|
-
catch (
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
catch (e_3) {
|
|
177
|
+
env_3.error = e_3;
|
|
178
|
+
env_3.hasError = true;
|
|
166
179
|
}
|
|
167
180
|
finally {
|
|
168
|
-
__disposeResources(
|
|
181
|
+
__disposeResources(env_3);
|
|
169
182
|
}
|
|
170
183
|
}
|
|
171
184
|
readFileSync;
|
|
172
185
|
export function writeFileSync(path, data, _options = {}) {
|
|
173
|
-
const
|
|
186
|
+
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
174
187
|
try {
|
|
175
188
|
const options = normalizeOptions(_options, 'utf8', 'w+', 0o644);
|
|
176
189
|
const flag = flags.parse(options.flag);
|
|
@@ -184,7 +197,7 @@ export function writeFileSync(path, data, _options = {}) {
|
|
|
184
197
|
if (!encodedData) {
|
|
185
198
|
throw new Exception(Errno.EINVAL, 'Data not specified');
|
|
186
199
|
}
|
|
187
|
-
const file = __addDisposableResource(
|
|
200
|
+
const file = __addDisposableResource(env_4, typeof path == 'number'
|
|
188
201
|
? fromFD(this, path)
|
|
189
202
|
: _sync.open.call(this, path.toString(), {
|
|
190
203
|
flag,
|
|
@@ -194,12 +207,12 @@ export function writeFileSync(path, data, _options = {}) {
|
|
|
194
207
|
file.writeSync(encodedData, 0, encodedData.byteLength, 0);
|
|
195
208
|
emitChange(this, 'change', path.toString());
|
|
196
209
|
}
|
|
197
|
-
catch (
|
|
198
|
-
|
|
199
|
-
|
|
210
|
+
catch (e_4) {
|
|
211
|
+
env_4.error = e_4;
|
|
212
|
+
env_4.hasError = true;
|
|
200
213
|
}
|
|
201
214
|
finally {
|
|
202
|
-
__disposeResources(
|
|
215
|
+
__disposeResources(env_4);
|
|
203
216
|
}
|
|
204
217
|
}
|
|
205
218
|
writeFileSync;
|
|
@@ -324,15 +337,27 @@ export function futimesSync(fd, atime, mtime) {
|
|
|
324
337
|
}
|
|
325
338
|
futimesSync;
|
|
326
339
|
export function rmdirSync(path) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
340
|
+
const env_5 = { stack: [], error: void 0, hasError: false };
|
|
341
|
+
try {
|
|
342
|
+
path = normalizePath(path);
|
|
343
|
+
const { fs, path: resolved } = _sync.resolve(this, path);
|
|
344
|
+
const stats = wrap(fs, 'statSync', { path, syscall: 'rmdir' })(resolved);
|
|
345
|
+
if (!isDirectory(stats))
|
|
346
|
+
throw UV('ENOTDIR', 'rmdir', path);
|
|
347
|
+
if (checkAccess && !hasAccess(this, stats, constants.W_OK))
|
|
348
|
+
throw UV('EACCES', 'rmdir', path);
|
|
349
|
+
const _ = __addDisposableResource(env_5, lockPathSync(fs, dirname(resolved), 'rw'), false);
|
|
350
|
+
wrap(fs, 'rmdirSync', path)(resolved);
|
|
351
|
+
cacheOf(fs).remove(resolved);
|
|
352
|
+
emitChange(this, 'rename', path.toString());
|
|
353
|
+
}
|
|
354
|
+
catch (e_5) {
|
|
355
|
+
env_5.error = e_5;
|
|
356
|
+
env_5.hasError = true;
|
|
357
|
+
}
|
|
358
|
+
finally {
|
|
359
|
+
__disposeResources(env_5);
|
|
360
|
+
}
|
|
336
361
|
}
|
|
337
362
|
rmdirSync;
|
|
338
363
|
export function mkdirSync(path, options) {
|
|
@@ -348,7 +373,7 @@ export function readdirSync(path, options) {
|
|
|
348
373
|
const rawEntries = _sync.readdir.call(this, path, options ?? undefined);
|
|
349
374
|
for (const raw of rawEntries) {
|
|
350
375
|
if (options?.withFileTypes) {
|
|
351
|
-
entries.push(Dirent.from(raw, options.encoding));
|
|
376
|
+
entries.push(Dirent.from(raw, options.encoding, path));
|
|
352
377
|
}
|
|
353
378
|
else if (options?.encoding == 'buffer') {
|
|
354
379
|
entries.push(Buffer.from(raw.path));
|
|
@@ -371,21 +396,21 @@ linkSync;
|
|
|
371
396
|
* @param type can be either `'dir'` or `'file'` (default is `'file'`)
|
|
372
397
|
*/
|
|
373
398
|
export function symlinkSync(target, path, type = 'file') {
|
|
374
|
-
const
|
|
399
|
+
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
375
400
|
try {
|
|
376
401
|
if (!['file', 'dir', 'junction'].includes(type))
|
|
377
402
|
throw new TypeError('Invalid symlink type: ' + type);
|
|
378
403
|
path = normalizePath(path);
|
|
379
|
-
const file = __addDisposableResource(
|
|
404
|
+
const file = __addDisposableResource(env_6, _sync.open.call(this, path, { flag: 'wx', mode: 0o644 }), false);
|
|
380
405
|
file.writeSync(encodeUTF8(normalizePath(target, true)));
|
|
381
406
|
file.chmodSync(constants.S_IFLNK);
|
|
382
407
|
}
|
|
383
|
-
catch (
|
|
384
|
-
|
|
385
|
-
|
|
408
|
+
catch (e_6) {
|
|
409
|
+
env_6.error = e_6;
|
|
410
|
+
env_6.hasError = true;
|
|
386
411
|
}
|
|
387
412
|
finally {
|
|
388
|
-
__disposeResources(
|
|
413
|
+
__disposeResources(env_6);
|
|
389
414
|
}
|
|
390
415
|
}
|
|
391
416
|
symlinkSync;
|
|
@@ -400,17 +425,17 @@ export function readlinkSync(path, options) {
|
|
|
400
425
|
}
|
|
401
426
|
readlinkSync;
|
|
402
427
|
export function chownSync(path, uid, gid) {
|
|
403
|
-
const
|
|
428
|
+
const env_7 = { stack: [], error: void 0, hasError: false };
|
|
404
429
|
try {
|
|
405
|
-
const handle = __addDisposableResource(
|
|
430
|
+
const handle = __addDisposableResource(env_7, _sync.open.call(this, path, { flag: 'r+', mode: constants.F_OK }), false);
|
|
406
431
|
handle.chownSync(uid, gid);
|
|
407
432
|
}
|
|
408
|
-
catch (
|
|
409
|
-
|
|
410
|
-
|
|
433
|
+
catch (e_7) {
|
|
434
|
+
env_7.error = e_7;
|
|
435
|
+
env_7.hasError = true;
|
|
411
436
|
}
|
|
412
437
|
finally {
|
|
413
|
-
__disposeResources(
|
|
438
|
+
__disposeResources(env_7);
|
|
414
439
|
}
|
|
415
440
|
}
|
|
416
441
|
chownSync;
|
|
@@ -421,7 +446,13 @@ export function lchownSync(path, uid, gid) {
|
|
|
421
446
|
}
|
|
422
447
|
lchownSync;
|
|
423
448
|
export function chmodSync(path, mode) {
|
|
424
|
-
|
|
449
|
+
let fd;
|
|
450
|
+
try {
|
|
451
|
+
fd = openSync.call(this, path, 'r+');
|
|
452
|
+
}
|
|
453
|
+
catch (e) {
|
|
454
|
+
throw setUVMessage(Object.assign(e, { syscall: 'chmod', path: normalizePath(path) }));
|
|
455
|
+
}
|
|
425
456
|
fchmodSync.call(this, fd, mode);
|
|
426
457
|
closeSync.call(this, fd);
|
|
427
458
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -25,7 +25,14 @@ export type Callback<Args extends unknown[] = [], NoError = null> = (e: Exceptio
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function normalizeMode(mode: unknown, def?: number): number;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Checks that `fd` is in the range Node accepts for a file descriptor.
|
|
29
|
+
* Note this throws a `RangeError` rather than an `Exception`, since that is what Node does.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateFD(fd: number): void;
|
|
33
|
+
/**
|
|
34
|
+
* Normalizes a time to milliseconds since the epoch.
|
|
35
|
+
* Note numbers and numeric strings are seconds, like Node's `toUnixTimestamp`.
|
|
29
36
|
* @internal
|
|
30
37
|
*/
|
|
31
38
|
export declare function normalizeTime(time: fs.TimeLike): number;
|
package/dist/utils.js
CHANGED
|
@@ -35,18 +35,36 @@ export function normalizeMode(mode, def) {
|
|
|
35
35
|
throw withErrno('EINVAL', 'Invalid mode: ' + mode?.toString());
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* The largest valid file descriptor, since Node validates them as 32-bit signed integers
|
|
39
|
+
* @internal @hidden
|
|
40
|
+
*/
|
|
41
|
+
const fd_max = 0x7fffffff;
|
|
42
|
+
/**
|
|
43
|
+
* Checks that `fd` is in the range Node accepts for a file descriptor.
|
|
44
|
+
* Note this throws a `RangeError` rather than an `Exception`, since that is what Node does.
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export function validateFD(fd) {
|
|
48
|
+
if (Number.isInteger(fd) && fd >= 0 && fd <= fd_max)
|
|
49
|
+
return;
|
|
50
|
+
throw Object.assign(new RangeError(`The value of "fd" is out of range. It must be >= 0 && <= ${fd_max}. Received ${fd}`), {
|
|
51
|
+
code: 'ERR_OUT_OF_RANGE',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Normalizes a time to milliseconds since the epoch.
|
|
56
|
+
* Note numbers and numeric strings are seconds, like Node's `toUnixTimestamp`.
|
|
39
57
|
* @internal
|
|
40
58
|
*/
|
|
41
59
|
export function normalizeTime(time) {
|
|
60
|
+
// Dates are already in milliseconds
|
|
42
61
|
if (time instanceof Date)
|
|
43
62
|
return time.getTime();
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
63
|
+
const seconds = Number(time);
|
|
64
|
+
if (!Number.isFinite(seconds))
|
|
48
65
|
throw withErrno('EINVAL', 'Invalid time.');
|
|
49
|
-
|
|
66
|
+
// Negative times mean "now"
|
|
67
|
+
return seconds < 0 ? Date.now() : seconds * 1000;
|
|
50
68
|
}
|
|
51
69
|
/**
|
|
52
70
|
* Normalizes a path
|
|
@@ -119,5 +137,6 @@ export async function waitOnline(worker) {
|
|
|
119
137
|
* @internal @hidden
|
|
120
138
|
*/
|
|
121
139
|
export function _tempDirName(prefix) {
|
|
122
|
-
|
|
140
|
+
// Like Node, the prefix is a path. A relative one is resolved against the working directory, not `/tmp`.
|
|
141
|
+
return `${normalizePath(prefix, true)}${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
123
142
|
}
|