@zenfs/core 2.6.2 → 2.6.3
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/single_buffer.js +34 -11
- package/dist/context.js +1 -0
- package/dist/internal/contexts.d.ts +3 -1
- package/dist/internal/contexts.js +11 -1
- package/dist/internal/inode.d.ts +2 -0
- package/dist/internal/inode.js +2 -0
- package/dist/internal/rpc.d.ts +4 -4
- package/dist/node/async.d.ts +11 -1
- package/dist/node/async.js +14 -35
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/promises.d.ts +17 -3
- package/dist/node/promises.js +32 -16
- package/dist/node/stats.d.ts +12 -0
- package/dist/node/stats.js +35 -6
- package/dist/node/sync.d.ts +39 -11
- package/dist/node/sync.js +41 -17
- package/dist/node/utf8stream.d.ts +99 -0
- package/dist/node/utf8stream.js +690 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +17 -0
- package/dist/vfs/shared.js +9 -7
- package/package.json +4 -4
- package/tests/backend/single-buffer-rotate.worker.js +19 -0
- package/tests/backend/single-buffer.test.ts +106 -0
- package/tests/common/context.test.ts +38 -0
- package/tests/common/glob.test.ts +85 -0
- package/tests/common/utf8stream.test.ts +164 -0
- package/tests/fs/stat.test.ts +30 -1
|
@@ -320,7 +320,7 @@ const sb_magic = 0x62732e7a; // 'z.sb'
|
|
|
320
320
|
* Shortcut for minor perf. bump
|
|
321
321
|
* @internal
|
|
322
322
|
*/
|
|
323
|
-
const
|
|
323
|
+
const kUsedBytes = 2;
|
|
324
324
|
/**
|
|
325
325
|
* The super block structure for a single-buffer file system
|
|
326
326
|
*/
|
|
@@ -502,16 +502,34 @@ let SuperBlock = (() => {
|
|
|
502
502
|
* @returns the new metadata block
|
|
503
503
|
*/
|
|
504
504
|
rotateMetadata() {
|
|
505
|
-
const
|
|
506
|
-
Atomics.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
505
|
+
const alignment = BigInt(Int32Array.BYTES_PER_ELEMENT), blockSize = BigInt(sizeof(MetadataBlock));
|
|
506
|
+
let used = Atomics.load(this, kUsedBytes), offset;
|
|
507
|
+
// Padding and block space must be reserved together because other writers can advance used_bytes at any time.
|
|
508
|
+
for (;;) {
|
|
509
|
+
const padding = (alignment - (used % alignment)) % alignment;
|
|
510
|
+
offset = used + padding;
|
|
511
|
+
const next = offset + blockSize;
|
|
512
|
+
if (next > this.total_bytes)
|
|
513
|
+
throw err(withErrno('ENOSPC', 'sbfs: not enough space for a new metadata block'));
|
|
514
|
+
const observed = Atomics.compareExchange(this, kUsedBytes, used, next);
|
|
515
|
+
if (observed === used)
|
|
516
|
+
break;
|
|
517
|
+
used = observed;
|
|
518
|
+
}
|
|
519
|
+
const metadata = new MetadataBlock(this.buffer, Number(offset));
|
|
520
|
+
const offsets = new Uint32Array(this.buffer, this.byteOffset, sizeof(SuperBlock) / Uint32Array.BYTES_PER_ELEMENT);
|
|
521
|
+
let previous = Atomics.load(offsets, kMetadataOffset);
|
|
522
|
+
for (;;) {
|
|
523
|
+
metadata.previous_offset = previous;
|
|
524
|
+
_update(metadata);
|
|
525
|
+
const observed = Atomics.compareExchange(offsets, kMetadataOffset, previous, metadata.byteOffset);
|
|
526
|
+
if (observed === previous)
|
|
527
|
+
break;
|
|
528
|
+
previous = observed;
|
|
529
|
+
}
|
|
510
530
|
this.metadata = metadata;
|
|
511
|
-
this.metadata_offset = metadata.byteOffset;
|
|
512
|
-
_update(metadata);
|
|
513
531
|
_update(this);
|
|
514
|
-
debug(`sbfs: rotated metadata block at ${hex(metadata.previous_offset)} with new block at ${hex(
|
|
532
|
+
debug(`sbfs: rotated metadata block at ${hex(metadata.previous_offset)} with new block at ${hex(metadata.byteOffset)}`);
|
|
515
533
|
return metadata;
|
|
516
534
|
}
|
|
517
535
|
/**
|
|
@@ -545,6 +563,11 @@ let SuperBlock = (() => {
|
|
|
545
563
|
return SuperBlock = _classThis;
|
|
546
564
|
})();
|
|
547
565
|
export { SuperBlock };
|
|
566
|
+
/**
|
|
567
|
+
* Index of `SuperBlock.metadata_offset` in a `Uint32Array` view of the super block.
|
|
568
|
+
* @internal
|
|
569
|
+
*/
|
|
570
|
+
const kMetadataOffset = offsetof(SuperBlock, 'metadata_offset') / Uint32Array.BYTES_PER_ELEMENT;
|
|
548
571
|
/**
|
|
549
572
|
* Compute the checksum for a super block or metadata block.
|
|
550
573
|
* Note we don't include the checksum when computing a new one.
|
|
@@ -635,7 +658,7 @@ export class SingleBufferStore extends BufferView {
|
|
|
635
658
|
_update(block);
|
|
636
659
|
return;
|
|
637
660
|
}
|
|
638
|
-
entry.offset = Number(Atomics.add(this.superblock,
|
|
661
|
+
entry.offset = Number(Atomics.add(this.superblock, kUsedBytes, BigInt(data.length)));
|
|
639
662
|
entry.size = data.length;
|
|
640
663
|
this._u8.set(data, entry.offset);
|
|
641
664
|
_update(block);
|
|
@@ -657,7 +680,7 @@ export class SingleBufferStore extends BufferView {
|
|
|
657
680
|
entry = this.superblock.metadata.items[0];
|
|
658
681
|
}
|
|
659
682
|
const lock = __addDisposableResource(env_1, this.superblock.metadata.lock(), false);
|
|
660
|
-
const offset = Number(Atomics.add(this.superblock,
|
|
683
|
+
const offset = Number(Atomics.add(this.superblock, kUsedBytes, BigInt(data.length)));
|
|
661
684
|
entry.id = id;
|
|
662
685
|
entry.offset = offset;
|
|
663
686
|
entry.size = data.length;
|
package/dist/context.js
CHANGED
|
@@ -14,7 +14,7 @@ declare const kIsContext: unique symbol;
|
|
|
14
14
|
* @category Contexts
|
|
15
15
|
*/
|
|
16
16
|
export interface FSContext {
|
|
17
|
-
/**
|
|
17
|
+
/** Brand */
|
|
18
18
|
readonly [kIsContext]: boolean;
|
|
19
19
|
/** The unique ID of the context */
|
|
20
20
|
readonly id: number;
|
|
@@ -35,6 +35,8 @@ export interface FSContext {
|
|
|
35
35
|
/** The child contexts */
|
|
36
36
|
readonly children: FSContext[];
|
|
37
37
|
}
|
|
38
|
+
export declare function isContext(obj: unknown): obj is FSContext;
|
|
39
|
+
export declare function assertContext(ctx: unknown): asserts ctx is FSContext;
|
|
38
40
|
/**
|
|
39
41
|
* maybe an FS context
|
|
40
42
|
*/
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { createCredentials } from './credentials.js';
|
|
2
|
+
import { warn } from 'kerium/log';
|
|
3
|
+
import { withErrno } from 'kerium';
|
|
2
4
|
/**
|
|
3
5
|
* Symbol used for context branding
|
|
4
6
|
* @internal @hidden
|
|
5
7
|
*/
|
|
6
8
|
const kIsContext = Symbol('ZenFSContext');
|
|
9
|
+
export function isContext(obj) {
|
|
10
|
+
return typeof obj === 'object' && obj !== null && kIsContext in obj;
|
|
11
|
+
}
|
|
12
|
+
export function assertContext(ctx) {
|
|
13
|
+
if (!isContext(ctx))
|
|
14
|
+
throw warn(withErrno('EINVAL', 'Invalid context provided'));
|
|
15
|
+
}
|
|
7
16
|
/**
|
|
8
17
|
* The default/global context.
|
|
9
18
|
* @internal @hidden
|
|
@@ -20,7 +29,7 @@ export const defaultContext = {
|
|
|
20
29
|
children: [],
|
|
21
30
|
};
|
|
22
31
|
export function contextOf($) {
|
|
23
|
-
return
|
|
32
|
+
return isContext($) ? $ : defaultContext;
|
|
24
33
|
}
|
|
25
34
|
// 0 is reserved for the global/default context
|
|
26
35
|
let _nextId = 1;
|
|
@@ -33,6 +42,7 @@ let _nextId = 1;
|
|
|
33
42
|
* This exists so that `kIsContext` is not exported and to make sure the context is "secure".
|
|
34
43
|
*/
|
|
35
44
|
export function createChildContext(parent, init = {}) {
|
|
45
|
+
assertContext(parent);
|
|
36
46
|
const { root = parent.root, pwd = parent.pwd, credentials = structuredClone(parent.credentials) } = init;
|
|
37
47
|
const ctx = {
|
|
38
48
|
[kIsContext]: true,
|
package/dist/internal/inode.d.ts
CHANGED
|
@@ -243,6 +243,8 @@ export declare function isFIFO(metadata: {
|
|
|
243
243
|
export declare function hasAccess($: V_Context, inode: Pick<InodeLike, 'mode' | 'uid' | 'gid'>, access: number): boolean;
|
|
244
244
|
/**
|
|
245
245
|
* @hidden @internal
|
|
246
|
+
*
|
|
247
|
+
* @todo https://github.com/nodejs/node/pull/58836 support -1 for `*chown`
|
|
246
248
|
*/
|
|
247
249
|
export declare function _chown(stats: Partial<InodeLike>, uid: number, gid: number): boolean;
|
|
248
250
|
export {};
|
package/dist/internal/inode.js
CHANGED
package/dist/internal/rpc.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ExceptionJSON } from 'kerium';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Transferable } from 'node:worker_threads';
|
|
3
3
|
import type { WithOptional } from 'utilium';
|
|
4
4
|
import type { Backend, FilesystemOf } from '../backends/backend.js';
|
|
5
5
|
import type { PortFS } from '../backends/port.js';
|
|
6
6
|
import type { CreationOptions, FileSystem, UsageInfo } from '../internal/filesystem.js';
|
|
7
7
|
import '../polyfills.js';
|
|
8
8
|
export interface WebMessagePort {
|
|
9
|
-
postMessage(value: unknown, transfer?:
|
|
9
|
+
postMessage(value: unknown, transfer?: Transferable[]): void;
|
|
10
10
|
addEventListener(type: 'message', listener: (ev: {
|
|
11
11
|
data: any;
|
|
12
12
|
}) => void): void;
|
|
@@ -15,7 +15,7 @@ export interface WebMessagePort {
|
|
|
15
15
|
}) => void): void;
|
|
16
16
|
}
|
|
17
17
|
export interface NodeMessagePort {
|
|
18
|
-
postMessage(value: unknown, transfer?:
|
|
18
|
+
postMessage(value: unknown, transfer?: Transferable[]): void;
|
|
19
19
|
on(type: 'message', listener: (ev: any) => void): void;
|
|
20
20
|
off(type: 'message', listener: (ev: any) => void): void;
|
|
21
21
|
}
|
|
@@ -24,7 +24,7 @@ export type Channel = NodeMessagePort | WebMessagePort | WebSocket;
|
|
|
24
24
|
export interface Port<T extends Channel = Channel> {
|
|
25
25
|
readonly channel: T;
|
|
26
26
|
/** Send a request */
|
|
27
|
-
send<M extends Message>(message: M, transfer?:
|
|
27
|
+
send<M extends Message>(message: M, transfer?: Transferable[]): void;
|
|
28
28
|
/** Add a response handler */
|
|
29
29
|
addHandler<M extends Message>(handler: (message: M) => void): void;
|
|
30
30
|
/** Remove a response handler */
|
package/dist/node/async.d.ts
CHANGED
|
@@ -22,11 +22,21 @@ export declare function exists(this: V_Context, path: fs.PathLike, cb?: (exists:
|
|
|
22
22
|
export declare function stat(this: V_Context, path: fs.PathLike, callback: Callback<[Stats]>): void;
|
|
23
23
|
export declare function stat(this: V_Context, path: fs.PathLike, options: {
|
|
24
24
|
bigint?: false;
|
|
25
|
+
throwIfNoEntry?: true;
|
|
25
26
|
}, callback: Callback<[Stats]>): void;
|
|
26
27
|
export declare function stat(this: V_Context, path: fs.PathLike, options: {
|
|
27
28
|
bigint: true;
|
|
29
|
+
throwIfNoEntry?: true;
|
|
28
30
|
}, callback: Callback<[BigIntStats]>): void;
|
|
29
|
-
export declare function stat(this: V_Context, path: fs.PathLike, options:
|
|
31
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: {
|
|
32
|
+
bigint?: false;
|
|
33
|
+
throwIfNoEntry: false;
|
|
34
|
+
}, callback: Callback<[Stats | undefined]>): void;
|
|
35
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: {
|
|
36
|
+
bigint: true;
|
|
37
|
+
throwIfNoEntry: false;
|
|
38
|
+
}, callback: Callback<[BigIntStats | undefined]>): void;
|
|
39
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.StatOptions, callback: Callback<[Stats | BigIntStats | undefined]>): void;
|
|
30
40
|
/**
|
|
31
41
|
* Asynchronous `lstat`.
|
|
32
42
|
* `lstat()` is identical to `stat()`, except that if path is a symbolic link,
|
package/dist/node/async.js
CHANGED
|
@@ -148,47 +148,26 @@ fdatasync;
|
|
|
148
148
|
export function write(fd, data, cbPosOff, cbLenEnc, cbPosEnc, cb = nop) {
|
|
149
149
|
let buffer, offset, length, position, encoding;
|
|
150
150
|
const handle = new promises.FileHandle(this, fd);
|
|
151
|
+
const _cb = ([cbPosOff, cbLenEnc, cbPosEnc].find(arg => typeof arg === 'function') ?? cb);
|
|
151
152
|
if (typeof data === 'string') {
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// (fd, string, cb)
|
|
157
|
-
cb = cbPosOff;
|
|
158
|
-
break;
|
|
159
|
-
case 'number':
|
|
160
|
-
// (fd, string, position, encoding?, cb?)
|
|
161
|
-
position = cbPosOff;
|
|
162
|
-
encoding = typeof cbLenEnc === 'string' ? cbLenEnc : 'utf8';
|
|
163
|
-
cb = typeof cbPosEnc === 'function' ? cbPosEnc : cb;
|
|
164
|
-
break;
|
|
165
|
-
default:
|
|
166
|
-
// ...try to find the callback and get out of here!
|
|
167
|
-
cb = (typeof cbLenEnc === 'function' ? cbLenEnc : typeof cbPosEnc === 'function' ? cbPosEnc : cb);
|
|
168
|
-
cb(withErrno('EINVAL'));
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
buffer = Buffer.from(data);
|
|
153
|
+
// (fd, string, [position?, [encoding?]], cb?)
|
|
154
|
+
position = typeof cbPosOff === 'number' ? cbPosOff : null;
|
|
155
|
+
encoding = typeof cbLenEnc === 'string' ? cbLenEnc : 'utf8';
|
|
156
|
+
buffer = Buffer.from(data, encoding);
|
|
172
157
|
offset = 0;
|
|
173
|
-
length = buffer.
|
|
174
|
-
const _cb = cb;
|
|
175
|
-
handle
|
|
176
|
-
.write(buffer, offset, length, position)
|
|
177
|
-
.then(({ bytesWritten }) => _cb(null, bytesWritten, buffer.toString(encoding)))
|
|
178
|
-
.catch(_cb);
|
|
158
|
+
length = buffer.byteLength;
|
|
179
159
|
}
|
|
180
160
|
else {
|
|
181
|
-
//
|
|
182
|
-
buffer = Buffer.from(data.buffer);
|
|
183
|
-
offset = cbPosOff;
|
|
184
|
-
length = cbLenEnc;
|
|
161
|
+
// (fd, buffer, [offset?, [length?, [position?]]], cb?)
|
|
162
|
+
buffer = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
163
|
+
offset = typeof cbPosOff === 'number' ? cbPosOff : 0;
|
|
164
|
+
length = typeof cbLenEnc === 'number' ? cbLenEnc : buffer.byteLength - offset;
|
|
185
165
|
position = typeof cbPosEnc === 'number' ? cbPosEnc : null;
|
|
186
|
-
const _cb = (typeof cbPosEnc === 'function' ? cbPosEnc : cb);
|
|
187
|
-
void handle
|
|
188
|
-
.write(buffer, offset, length, position)
|
|
189
|
-
.then(({ bytesWritten }) => _cb(null, bytesWritten, buffer))
|
|
190
|
-
.catch(_cb);
|
|
191
166
|
}
|
|
167
|
+
handle
|
|
168
|
+
.write(buffer, offset, length, position)
|
|
169
|
+
.then(({ bytesWritten }) => _cb(null, bytesWritten, typeof data === 'string' ? data : buffer))
|
|
170
|
+
.catch(_cb);
|
|
192
171
|
}
|
|
193
172
|
write;
|
|
194
173
|
/**
|
package/dist/node/index.d.ts
CHANGED
package/dist/node/index.js
CHANGED
package/dist/node/promises.d.ts
CHANGED
|
@@ -180,11 +180,25 @@ export declare function rename(this: V_Context, oldPath: fs.PathLike, newPath: f
|
|
|
180
180
|
* Test whether or not `path` exists by checking with the file system.
|
|
181
181
|
*/
|
|
182
182
|
export declare function exists(this: V_Context, path: fs.PathLike): Promise<boolean>;
|
|
183
|
-
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.BigIntOptions
|
|
184
|
-
|
|
183
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.BigIntOptions & {
|
|
184
|
+
throwIfNoEntry?: true;
|
|
185
|
+
}): Promise<BigIntStats>;
|
|
186
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options?: fs.StatOptions & {
|
|
185
187
|
bigint?: false;
|
|
188
|
+
throwIfNoEntry?: true;
|
|
186
189
|
}): Promise<Stats>;
|
|
187
|
-
export declare function stat(this: V_Context, path: fs.PathLike, options
|
|
190
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
191
|
+
bigint?: false;
|
|
192
|
+
throwIfNoEntry: false;
|
|
193
|
+
}): Promise<Stats | undefined>;
|
|
194
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
195
|
+
bigint: true;
|
|
196
|
+
throwIfNoEntry: false;
|
|
197
|
+
}): Promise<BigIntStats | undefined>;
|
|
198
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
199
|
+
throwIfNoEntry?: true;
|
|
200
|
+
}): Promise<Stats | BigIntStats>;
|
|
201
|
+
export declare function stat(this: V_Context, path: fs.PathLike, options?: fs.StatOptions): Promise<Stats | BigIntStats | undefined>;
|
|
188
202
|
/**
|
|
189
203
|
* `lstat`.
|
|
190
204
|
* `lstat()` is identical to `stat()`, except that if path is a symbolic link,
|
package/dist/node/promises.js
CHANGED
|
@@ -54,10 +54,11 @@ import { Buffer } from 'buffer';
|
|
|
54
54
|
import { Exception, rethrow, UV } from 'kerium';
|
|
55
55
|
import { encodeUTF8 } from 'utilium';
|
|
56
56
|
import * as constants from '../constants.js';
|
|
57
|
+
import { contextOf } from '../internal/contexts.js';
|
|
57
58
|
import { hasAccess, InodeFlags, isDirectory } from '../internal/inode.js';
|
|
58
|
-
import { dirname, join, matchesGlob, resolve } from '../path.js';
|
|
59
|
+
import { dirname, join, matchesGlob, relative, resolve } from '../path.js';
|
|
59
60
|
import '../polyfills.js';
|
|
60
|
-
import { _tempDirName, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime, validateFD } from '../utils.js';
|
|
61
|
+
import { _isNoEntry, _tempDirName, globToRegex, normalizeMode, normalizeOptions, normalizePath, normalizeTime, validateFD } from '../utils.js';
|
|
61
62
|
import * as _async from '../vfs/async.js';
|
|
62
63
|
import { checkAccess } from '../vfs/config.js';
|
|
63
64
|
import { deleteFD, fromFD, toFD } from '../vfs/file.js';
|
|
@@ -541,7 +542,15 @@ export async function exists(path) {
|
|
|
541
542
|
}
|
|
542
543
|
}
|
|
543
544
|
export async function stat(path, options) {
|
|
544
|
-
|
|
545
|
+
let stats;
|
|
546
|
+
try {
|
|
547
|
+
stats = await _async.stat.call(this, path, false);
|
|
548
|
+
}
|
|
549
|
+
catch (e) {
|
|
550
|
+
if (options?.throwIfNoEntry === false && _isNoEntry(e))
|
|
551
|
+
return;
|
|
552
|
+
throw e;
|
|
553
|
+
}
|
|
545
554
|
return options?.bigint ? new BigIntStats(stats) : new Stats(stats);
|
|
546
555
|
}
|
|
547
556
|
stat;
|
|
@@ -1113,8 +1122,10 @@ export async function statfs(path, opts) {
|
|
|
1113
1122
|
}
|
|
1114
1123
|
export function glob(pattern, opt) {
|
|
1115
1124
|
pattern = Array.isArray(pattern) ? pattern : [pattern];
|
|
1116
|
-
const
|
|
1117
|
-
const
|
|
1125
|
+
const $ = contextOf(this);
|
|
1126
|
+
const { cwd = $.pwd, withFileTypes = false, exclude = () => false, followSymlinks = false } = opt || {};
|
|
1127
|
+
const base = resolve.call($, cwd instanceof URL ? cwd.pathname : cwd);
|
|
1128
|
+
const normalizedPatterns = pattern.map(p => (p.startsWith('/') ? relative.call($, base, p) : p));
|
|
1118
1129
|
const hasGlobStar = normalizedPatterns.some(p => p.includes('**'));
|
|
1119
1130
|
const patternBases = normalizedPatterns.map(p => {
|
|
1120
1131
|
const firstGlob = p.search(/[*?[\]{]/);
|
|
@@ -1124,23 +1135,28 @@ export function glob(pattern, opt) {
|
|
|
1124
1135
|
return lastSlash === -1 ? '' : p.slice(0, lastSlash);
|
|
1125
1136
|
});
|
|
1126
1137
|
const regexPatterns = normalizedPatterns.map(globToRegex);
|
|
1138
|
+
async function shouldDescend(path, relativePath) {
|
|
1139
|
+
const isNamed = patternBases.some(base => relativePath === base || base.startsWith(relativePath + '/'));
|
|
1140
|
+
const inScope = hasGlobStar || isNamed;
|
|
1141
|
+
const stats = await lstat.call($, path);
|
|
1142
|
+
if (!stats.isSymbolicLink())
|
|
1143
|
+
return inScope && stats.isDirectory();
|
|
1144
|
+
return inScope && (followSymlinks || isNamed) && !!(await stat.call($, path, { throwIfNoEntry: false }))?.isDirectory();
|
|
1145
|
+
}
|
|
1127
1146
|
async function* recursiveList(dir) {
|
|
1128
|
-
const entries = await readdir(dir, { withFileTypes, encoding: 'utf8' });
|
|
1147
|
+
const entries = await readdir.call($, dir, { withFileTypes, encoding: 'utf8' });
|
|
1129
1148
|
for (const entry of entries) {
|
|
1130
1149
|
const fullPath = join(dir, withFileTypes ? entry.name : entry);
|
|
1131
|
-
|
|
1150
|
+
const relPath = relative.call($, base, fullPath);
|
|
1151
|
+
if (typeof exclude != 'function' ? exclude.some(p => matchesGlob(p, relPath)) : exclude((withFileTypes ? entry : relPath)))
|
|
1132
1152
|
continue;
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
if (regexPatterns.some(rx => rx.test(relativePath))) {
|
|
1140
|
-
yield withFileTypes ? entry : relativePath;
|
|
1153
|
+
if (await shouldDescend(fullPath, relPath))
|
|
1154
|
+
yield* recursiveList(fullPath);
|
|
1155
|
+
if (regexPatterns.some(rx => rx.test(relPath))) {
|
|
1156
|
+
yield withFileTypes ? entry : relPath;
|
|
1141
1157
|
}
|
|
1142
1158
|
}
|
|
1143
1159
|
}
|
|
1144
|
-
return recursiveList(
|
|
1160
|
+
return recursiveList(base);
|
|
1145
1161
|
}
|
|
1146
1162
|
glob;
|
package/dist/node/stats.d.ts
CHANGED
|
@@ -91,24 +91,32 @@ export declare abstract class StatsCommon<T extends number | bigint> implements
|
|
|
91
91
|
atimeMs: T;
|
|
92
92
|
get atime(): Date;
|
|
93
93
|
set atime(value: Date);
|
|
94
|
+
get atimeInstant(): Temporal.Instant;
|
|
95
|
+
set atimeInstant(value: Temporal.Instant);
|
|
94
96
|
/**
|
|
95
97
|
* Time of last modification, since epoch
|
|
96
98
|
*/
|
|
97
99
|
mtimeMs: T;
|
|
98
100
|
get mtime(): Date;
|
|
99
101
|
set mtime(value: Date);
|
|
102
|
+
get mtimeInstant(): Temporal.Instant;
|
|
103
|
+
set mtimeInstant(value: Temporal.Instant);
|
|
100
104
|
/**
|
|
101
105
|
* Time of last time file status was changed, since epoch
|
|
102
106
|
*/
|
|
103
107
|
ctimeMs: T;
|
|
104
108
|
get ctime(): Date;
|
|
105
109
|
set ctime(value: Date);
|
|
110
|
+
get ctimeInstant(): Temporal.Instant;
|
|
111
|
+
set ctimeInstant(value: Temporal.Instant);
|
|
106
112
|
/**
|
|
107
113
|
* Time of file creation, since epoch
|
|
108
114
|
*/
|
|
109
115
|
birthtimeMs: T;
|
|
110
116
|
get birthtime(): Date;
|
|
111
117
|
set birthtime(value: Date);
|
|
118
|
+
get birthtimeInstant(): Temporal.Instant;
|
|
119
|
+
set birthtimeInstant(value: Temporal.Instant);
|
|
112
120
|
/**
|
|
113
121
|
* Size of the item in bytes.
|
|
114
122
|
* For directories/symlinks, this is normally the size of the struct that represents the item.
|
|
@@ -193,6 +201,8 @@ export declare class StatsFs implements Node.StatsFsBase<number> {
|
|
|
193
201
|
bavail: number;
|
|
194
202
|
/** Total file nodes in file system. */
|
|
195
203
|
files: number;
|
|
204
|
+
/** Fundamental file system block size. */
|
|
205
|
+
frsize: number;
|
|
196
206
|
/** Free file nodes in file system. */
|
|
197
207
|
ffree: number;
|
|
198
208
|
}
|
|
@@ -212,6 +222,8 @@ export declare class BigIntStatsFs implements Node.StatsFsBase<bigint> {
|
|
|
212
222
|
bavail: bigint;
|
|
213
223
|
/** Total file nodes in file system. */
|
|
214
224
|
files: bigint;
|
|
225
|
+
/** Fundamental file system block size. */
|
|
226
|
+
frsize: bigint;
|
|
215
227
|
/** Free file nodes in file system. */
|
|
216
228
|
ffree: bigint;
|
|
217
229
|
}
|
package/dist/node/stats.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { pick } from 'utilium';
|
|
2
|
-
import { _inode_fields, hasAccess } from '../internal/inode.js';
|
|
3
2
|
import * as c from '../constants.js';
|
|
4
|
-
|
|
3
|
+
import { _inode_fields, hasAccess } from '../internal/inode.js';
|
|
4
|
+
import { _temporal } from '../utils.js';
|
|
5
|
+
const _nsMultiplier = BigInt(1_000_000);
|
|
5
6
|
/**
|
|
6
7
|
* Provides information about a particular entry in the file system.
|
|
7
8
|
* Common code used by both Stats and BigIntStats.
|
|
@@ -56,6 +57,12 @@ export class StatsCommon {
|
|
|
56
57
|
set atime(value) {
|
|
57
58
|
this.atimeMs = this._convert(value.getTime());
|
|
58
59
|
}
|
|
60
|
+
get atimeInstant() {
|
|
61
|
+
return _temporal().Instant.fromEpochMilliseconds(Number(this.atimeMs));
|
|
62
|
+
}
|
|
63
|
+
set atimeInstant(value) {
|
|
64
|
+
this.atimeMs = this._convert(value.epochMilliseconds);
|
|
65
|
+
}
|
|
59
66
|
/**
|
|
60
67
|
* Time of last modification, since epoch
|
|
61
68
|
*/
|
|
@@ -66,6 +73,12 @@ export class StatsCommon {
|
|
|
66
73
|
set mtime(value) {
|
|
67
74
|
this.mtimeMs = this._convert(value.getTime());
|
|
68
75
|
}
|
|
76
|
+
get mtimeInstant() {
|
|
77
|
+
return _temporal().Instant.fromEpochMilliseconds(Number(this.mtimeMs));
|
|
78
|
+
}
|
|
79
|
+
set mtimeInstant(value) {
|
|
80
|
+
this.mtimeMs = this._convert(value.epochMilliseconds);
|
|
81
|
+
}
|
|
69
82
|
/**
|
|
70
83
|
* Time of last time file status was changed, since epoch
|
|
71
84
|
*/
|
|
@@ -76,6 +89,12 @@ export class StatsCommon {
|
|
|
76
89
|
set ctime(value) {
|
|
77
90
|
this.ctimeMs = this._convert(value.getTime());
|
|
78
91
|
}
|
|
92
|
+
get ctimeInstant() {
|
|
93
|
+
return _temporal().Instant.fromEpochMilliseconds(Number(this.ctimeMs));
|
|
94
|
+
}
|
|
95
|
+
set ctimeInstant(value) {
|
|
96
|
+
this.ctimeMs = this._convert(value.epochMilliseconds);
|
|
97
|
+
}
|
|
79
98
|
/**
|
|
80
99
|
* Time of file creation, since epoch
|
|
81
100
|
*/
|
|
@@ -86,6 +105,12 @@ export class StatsCommon {
|
|
|
86
105
|
set birthtime(value) {
|
|
87
106
|
this.birthtimeMs = this._convert(value.getTime());
|
|
88
107
|
}
|
|
108
|
+
get birthtimeInstant() {
|
|
109
|
+
return _temporal().Instant.fromEpochMilliseconds(Number(this.birthtimeMs));
|
|
110
|
+
}
|
|
111
|
+
set birthtimeInstant(value) {
|
|
112
|
+
this.birthtimeMs = this._convert(value.epochMilliseconds);
|
|
113
|
+
}
|
|
89
114
|
/**
|
|
90
115
|
* Size of the item in bytes.
|
|
91
116
|
* For directories/symlinks, this is normally the size of the struct that represents the item.
|
|
@@ -156,16 +181,16 @@ export class StatsCommon {
|
|
|
156
181
|
return hasAccess(context, this._isBigint ? new Stats(this) : this, mode);
|
|
157
182
|
}
|
|
158
183
|
get atimeNs() {
|
|
159
|
-
return BigInt(this.atimeMs) *
|
|
184
|
+
return BigInt(this.atimeMs) * _nsMultiplier;
|
|
160
185
|
}
|
|
161
186
|
get mtimeNs() {
|
|
162
|
-
return BigInt(this.mtimeMs) *
|
|
187
|
+
return BigInt(this.mtimeMs) * _nsMultiplier;
|
|
163
188
|
}
|
|
164
189
|
get ctimeNs() {
|
|
165
|
-
return BigInt(this.ctimeMs) *
|
|
190
|
+
return BigInt(this.ctimeMs) * _nsMultiplier;
|
|
166
191
|
}
|
|
167
192
|
get birthtimeNs() {
|
|
168
|
-
return BigInt(this.birthtimeMs) *
|
|
193
|
+
return BigInt(this.birthtimeMs) * _nsMultiplier;
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
196
|
/**
|
|
@@ -218,6 +243,8 @@ export class StatsFs {
|
|
|
218
243
|
bavail = 0;
|
|
219
244
|
/** Total file nodes in file system. */
|
|
220
245
|
files = c.size_max;
|
|
246
|
+
/** Fundamental file system block size. */
|
|
247
|
+
frsize = 4096;
|
|
221
248
|
/** Free file nodes in file system. */
|
|
222
249
|
ffree = c.size_max;
|
|
223
250
|
}
|
|
@@ -237,6 +264,8 @@ export class BigIntStatsFs {
|
|
|
237
264
|
bavail = BigInt(0);
|
|
238
265
|
/** Total file nodes in file system. */
|
|
239
266
|
files = BigInt(c.size_max);
|
|
267
|
+
/** Fundamental file system block size. */
|
|
268
|
+
frsize = BigInt(4096);
|
|
240
269
|
/** Free file nodes in file system. */
|
|
241
270
|
ffree = BigInt(c.size_max);
|
|
242
271
|
}
|
package/dist/node/sync.d.ts
CHANGED
|
@@ -10,23 +10,51 @@ export declare function renameSync(this: V_Context, oldPath: fs.PathLike, newPat
|
|
|
10
10
|
* Test whether or not `path` exists by checking with the file system.
|
|
11
11
|
*/
|
|
12
12
|
export declare function existsSync(this: V_Context, path: fs.PathLike): boolean;
|
|
13
|
-
export declare function statSync(this: V_Context, path: fs.PathLike, options?: {
|
|
14
|
-
bigint?:
|
|
13
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options?: fs.StatOptions & {
|
|
14
|
+
bigint?: false;
|
|
15
|
+
throwIfNoEntry?: true;
|
|
15
16
|
}): Stats;
|
|
16
|
-
export declare function statSync(this: V_Context, path: fs.PathLike, options: {
|
|
17
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
17
18
|
bigint: true;
|
|
19
|
+
throwIfNoEntry?: true;
|
|
18
20
|
}): BigIntStats;
|
|
21
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
22
|
+
bigint?: false;
|
|
23
|
+
throwIfNoEntry: false;
|
|
24
|
+
}): Stats | undefined;
|
|
25
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
26
|
+
bigint: true;
|
|
27
|
+
throwIfNoEntry: false;
|
|
28
|
+
}): BigIntStats | undefined;
|
|
29
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
30
|
+
throwIfNoEntry?: true;
|
|
31
|
+
}): Stats | BigIntStats;
|
|
32
|
+
export declare function statSync(this: V_Context, path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats | undefined;
|
|
19
33
|
/**
|
|
20
34
|
* Synchronous `lstat`.
|
|
21
35
|
* `lstat()` is identical to `stat()`, except that if path is a symbolic link,
|
|
22
36
|
* then the link itself is stat-ed, not the file that it refers to.
|
|
23
37
|
*/
|
|
24
|
-
export declare function lstatSync(this: V_Context, path: fs.PathLike, options?: {
|
|
25
|
-
bigint?:
|
|
38
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options?: fs.StatOptions & {
|
|
39
|
+
bigint?: false;
|
|
40
|
+
throwIfNoEntry?: true;
|
|
26
41
|
}): Stats;
|
|
27
|
-
export declare function lstatSync(this: V_Context, path: fs.PathLike, options: {
|
|
42
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
28
43
|
bigint: true;
|
|
44
|
+
throwIfNoEntry?: true;
|
|
29
45
|
}): BigIntStats;
|
|
46
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
47
|
+
bigint?: false;
|
|
48
|
+
throwIfNoEntry: false;
|
|
49
|
+
}): Stats | undefined;
|
|
50
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
51
|
+
bigint: true;
|
|
52
|
+
throwIfNoEntry: false;
|
|
53
|
+
}): BigIntStats | undefined;
|
|
54
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options: fs.StatOptions & {
|
|
55
|
+
throwIfNoEntry?: true;
|
|
56
|
+
}): Stats | BigIntStats;
|
|
57
|
+
export declare function lstatSync(this: V_Context, path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats | undefined;
|
|
30
58
|
export declare function truncateSync(this: V_Context, path: fs.PathLike, len?: number | null): void;
|
|
31
59
|
export declare function unlinkSync(this: V_Context, path: fs.PathLike): void;
|
|
32
60
|
/**
|
|
@@ -94,7 +122,7 @@ export declare function fdatasyncSync(this: V_Context, fd: number): void;
|
|
|
94
122
|
*/
|
|
95
123
|
export declare function writeSync(this: V_Context, fd: number, data: ArrayBufferView, offset?: number | null, length?: number | null, position?: number | null): number;
|
|
96
124
|
export declare function writeSync(this: V_Context, fd: number, data: string, position?: number | null, encoding?: BufferEncoding | null): number;
|
|
97
|
-
export declare function readSync(this: V_Context, fd: number, buffer: ArrayBufferView, options?: fs.
|
|
125
|
+
export declare function readSync(this: V_Context, fd: number, buffer: ArrayBufferView, options?: fs.ReadOptions): number;
|
|
98
126
|
export declare function readSync(this: V_Context, fd: number, buffer: ArrayBufferView, offset: number, length: number, position?: fs.ReadPosition | null): number;
|
|
99
127
|
export declare function fchownSync(this: V_Context, fd: number, uid: number, gid: number): void;
|
|
100
128
|
export declare function fchmodSync(this: V_Context, fd: number, mode: number | string): void;
|
|
@@ -246,7 +274,7 @@ export declare function statfsSync(this: V_Context, path: fs.PathLike, options?:
|
|
|
246
274
|
/**
|
|
247
275
|
* Retrieves the files matching the specified pattern.
|
|
248
276
|
*/
|
|
249
|
-
export declare function globSync(pattern: string | readonly string[]): string[];
|
|
250
|
-
export declare function globSync(pattern: string | readonly string[], options: fs.GlobOptionsWithFileTypes): Dirent[];
|
|
251
|
-
export declare function globSync(pattern: string | readonly string[], options: fs.GlobOptionsWithoutFileTypes): string[];
|
|
252
|
-
export declare function globSync(pattern: string | readonly string[], options: fs.GlobOptions): Dirent[] | string[];
|
|
277
|
+
export declare function globSync(this: V_Context, pattern: string | readonly string[]): string[];
|
|
278
|
+
export declare function globSync(this: V_Context, pattern: string | readonly string[], options: fs.GlobOptionsWithFileTypes): Dirent[];
|
|
279
|
+
export declare function globSync(this: V_Context, pattern: string | readonly string[], options: fs.GlobOptionsWithoutFileTypes): string[];
|
|
280
|
+
export declare function globSync(this: V_Context, pattern: string | readonly string[], options: fs.GlobOptions): Dirent[] | string[];
|