@zenfs/core 1.10.0 → 1.10.2
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/{overlay.d.ts → cow.d.ts} +91 -41
- package/dist/backends/{overlay.js → cow.js} +136 -196
- package/dist/backends/index.d.ts +1 -1
- package/dist/backends/index.js +1 -1
- package/dist/backends/port/fs.js +1 -1
- package/dist/backends/single_buffer.js +4 -4
- package/dist/backends/store/fs.js +3 -3
- package/dist/index.d.ts +1 -7
- package/dist/index.js +2 -0
- package/dist/internal/devices.js +1 -1
- package/dist/internal/file.js +7 -7
- package/dist/internal/log.d.ts +6 -5
- package/dist/internal/log.js +48 -7
- package/dist/mixins/async.js +21 -25
- package/dist/mixins/shared.d.ts +2 -2
- package/dist/polyfills.d.ts +0 -4
- package/dist/polyfills.js +16 -13
- package/dist/vfs/async.js +42 -19
- package/dist/vfs/promises.d.ts +7 -13
- package/dist/vfs/promises.js +55 -58
- package/dist/vfs/shared.js +2 -2
- package/dist/vfs/streams.d.ts +2 -2
- package/dist/vfs/streams.js +24 -18
- package/dist/vfs/sync.js +5 -5
- package/package.json +3 -3
- package/readme.md +1 -4
- package/tests/common/mutex.test.ts +1 -1
- package/tests/fetch/server.js +1 -1
- package/tests/fs/directory.test.ts +11 -59
- package/tests/fs/errors.test.ts +1 -1
- package/tests/fs/stat.test.ts +2 -6
- package/tests/fs/streams.test.ts +71 -66
- package/tests/setup/cow.ts +13 -0
- package/tests/tsconfig.json +1 -4
- package/types/README.md +1 -0
- package/types/readable-stream.d.ts +17 -0
- package/tests/setup/_overlay.ts +0 -7
package/dist/backends/index.d.ts
CHANGED
package/dist/backends/index.js
CHANGED
package/dist/backends/port/fs.js
CHANGED
|
@@ -124,7 +124,7 @@ const _Port = {
|
|
|
124
124
|
validator(port) {
|
|
125
125
|
// Check for a `postMessage` function.
|
|
126
126
|
if (typeof (port === null || port === void 0 ? void 0 : port.postMessage) != 'function') {
|
|
127
|
-
throw err(new ErrnoError(Errno.EINVAL, 'option must be a port
|
|
127
|
+
throw err(new ErrnoError(Errno.EINVAL, 'option must be a port'));
|
|
128
128
|
}
|
|
129
129
|
},
|
|
130
130
|
},
|
|
@@ -265,7 +265,7 @@ let SuperBlock = (() => {
|
|
|
265
265
|
__runInitializers(this, __padding_extraInitializers);
|
|
266
266
|
this.store = store;
|
|
267
267
|
if (store._view.getUint32(offsetof(SuperBlock, 'magic'), true) != sb_magic) {
|
|
268
|
-
warn('SingleBuffer: Invalid magic value
|
|
268
|
+
warn('SingleBuffer: Invalid magic value, assuming this is a fresh super block');
|
|
269
269
|
this.metadata = new MetadataBlock(this);
|
|
270
270
|
this.used_bytes = BigInt(sizeof(SuperBlock) + sizeof(MetadataBlock));
|
|
271
271
|
this.total_bytes = BigInt(store._buffer.byteLength);
|
|
@@ -371,7 +371,7 @@ export class SingleBufferStore {
|
|
|
371
371
|
this.name = 'sbfs';
|
|
372
372
|
this.id = 0x73626673; // 'sbfs'
|
|
373
373
|
if (buffer.byteLength < sizeof(SuperBlock) + sizeof(MetadataBlock))
|
|
374
|
-
throw crit(new ErrnoError(Errno.EINVAL, 'SingleBuffer: Buffer is too small for a file system
|
|
374
|
+
throw crit(new ErrnoError(Errno.EINVAL, 'SingleBuffer: Buffer is too small for a file system'));
|
|
375
375
|
this._view = !ArrayBuffer.isView(buffer) ? new DataView(buffer) : new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
376
376
|
this._buffer = !ArrayBuffer.isView(buffer) ? new Uint8Array(buffer) : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
377
377
|
this.superblock = new SuperBlock(this);
|
|
@@ -467,8 +467,8 @@ export class SingleBufferStore {
|
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
|
-
|
|
471
|
-
return;
|
|
470
|
+
sync() {
|
|
471
|
+
return Promise.resolve();
|
|
472
472
|
}
|
|
473
473
|
usage() {
|
|
474
474
|
return {
|
|
@@ -792,11 +792,11 @@ export class StoreFS extends FileSystem {
|
|
|
792
792
|
warn('Attempted to populate tables after initialization');
|
|
793
793
|
return;
|
|
794
794
|
}
|
|
795
|
-
debug('Populating tables with existing store metadata
|
|
795
|
+
debug('Populating tables with existing store metadata');
|
|
796
796
|
const tx = __addDisposableResource(env_23, this.transaction(), true);
|
|
797
797
|
const rootData = await tx.get(rootIno);
|
|
798
798
|
if (!rootData) {
|
|
799
|
-
notice('Store does not have a root inode
|
|
799
|
+
notice('Store does not have a root inode');
|
|
800
800
|
const inode = new Inode({ ino: rootIno, data: 1, mode: 0o777 | S_IFDIR });
|
|
801
801
|
await tx.set(inode.data, encodeUTF8('{}'));
|
|
802
802
|
this._add(rootIno, '/');
|
|
@@ -805,7 +805,7 @@ export class StoreFS extends FileSystem {
|
|
|
805
805
|
return;
|
|
806
806
|
}
|
|
807
807
|
if (rootData.length != __inode_sz) {
|
|
808
|
-
crit('Store contains an invalid root inode. Refusing to populate tables
|
|
808
|
+
crit('Store contains an invalid root inode. Refusing to populate tables');
|
|
809
809
|
return;
|
|
810
810
|
}
|
|
811
811
|
// Keep track of directories we have already traversed to avoid loops
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference path="../types/readable-stream.d.ts" preserve="true" />
|
|
1
2
|
export * from './backends/index.js';
|
|
2
3
|
export * from './config.js';
|
|
3
4
|
export * from './context.js';
|
|
@@ -9,10 +10,3 @@ export * from './vfs/index.js';
|
|
|
9
10
|
export { fs };
|
|
10
11
|
import * as fs from './vfs/index.js';
|
|
11
12
|
export default fs;
|
|
12
|
-
declare global {
|
|
13
|
-
/**
|
|
14
|
-
* Global VFS. Do not use unless absolutely needed.
|
|
15
|
-
* @hidden
|
|
16
|
-
*/
|
|
17
|
-
var __zenfs__: typeof fs;
|
|
18
|
-
}
|
package/dist/index.js
CHANGED
package/dist/internal/devices.js
CHANGED
|
@@ -241,7 +241,7 @@ export class DeviceFS extends StoreFS {
|
|
|
241
241
|
this._createDevice(fullDevice);
|
|
242
242
|
this._createDevice(randomDevice);
|
|
243
243
|
this._createDevice(consoleDevice);
|
|
244
|
-
debug('Added default devices
|
|
244
|
+
debug('Added default devices');
|
|
245
245
|
}
|
|
246
246
|
constructor() {
|
|
247
247
|
// Please don't store your temporary files in /dev.
|
package/dist/internal/file.js
CHANGED
|
@@ -280,7 +280,7 @@ export class PreloadFile extends File {
|
|
|
280
280
|
throw ErrnoError.With('EBADF', this.path, 'truncate');
|
|
281
281
|
this.dirty = true;
|
|
282
282
|
if (!isWriteable(this.flag)) {
|
|
283
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode
|
|
283
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
284
284
|
}
|
|
285
285
|
this.stats.mtimeMs = Date.now();
|
|
286
286
|
if (length > this._buffer.length) {
|
|
@@ -307,7 +307,7 @@ export class PreloadFile extends File {
|
|
|
307
307
|
if (this.closed)
|
|
308
308
|
throw ErrnoError.With('EBADF', this.path, 'write');
|
|
309
309
|
if (!isWriteable(this.flag)) {
|
|
310
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode
|
|
310
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
311
311
|
}
|
|
312
312
|
this.dirty = true;
|
|
313
313
|
const end = position + length;
|
|
@@ -353,7 +353,7 @@ export class PreloadFile extends File {
|
|
|
353
353
|
if (this.closed)
|
|
354
354
|
throw ErrnoError.With('EBADF', this.path, 'read');
|
|
355
355
|
if (!isReadable(this.flag)) {
|
|
356
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode
|
|
356
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode');
|
|
357
357
|
}
|
|
358
358
|
if (config.updateOnRead) {
|
|
359
359
|
this.dirty = true;
|
|
@@ -572,7 +572,7 @@ export class LazyFile extends File {
|
|
|
572
572
|
throw ErrnoError.With('EBADF', this.path, 'truncate');
|
|
573
573
|
this.dirty = true;
|
|
574
574
|
if (!isWriteable(this.flag)) {
|
|
575
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode
|
|
575
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
576
576
|
}
|
|
577
577
|
this.stats.mtimeMs = Date.now();
|
|
578
578
|
this.stats.size = length;
|
|
@@ -584,7 +584,7 @@ export class LazyFile extends File {
|
|
|
584
584
|
throw ErrnoError.With('EBADF', this.path, 'truncate');
|
|
585
585
|
this.dirty = true;
|
|
586
586
|
if (!isWriteable(this.flag)) {
|
|
587
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode
|
|
587
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
588
588
|
}
|
|
589
589
|
this.stats.mtimeMs = Date.now();
|
|
590
590
|
this.stats.size = length;
|
|
@@ -595,7 +595,7 @@ export class LazyFile extends File {
|
|
|
595
595
|
if (this.closed)
|
|
596
596
|
throw ErrnoError.With('EBADF', this.path, 'write');
|
|
597
597
|
if (!isWriteable(this.flag)) {
|
|
598
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode
|
|
598
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode');
|
|
599
599
|
}
|
|
600
600
|
this.dirty = true;
|
|
601
601
|
const end = position + length;
|
|
@@ -644,7 +644,7 @@ export class LazyFile extends File {
|
|
|
644
644
|
if (this.closed)
|
|
645
645
|
throw ErrnoError.With('EBADF', this.path, 'read');
|
|
646
646
|
if (!isReadable(this.flag))
|
|
647
|
-
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode
|
|
647
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode');
|
|
648
648
|
if (config.updateOnRead)
|
|
649
649
|
this.dirty = true;
|
|
650
650
|
this.stats.atimeMs = Date.now();
|
package/dist/internal/log.d.ts
CHANGED
|
@@ -88,16 +88,17 @@ export declare function log_deprecated(symbol: string): void;
|
|
|
88
88
|
*/
|
|
89
89
|
export declare const formats: {
|
|
90
90
|
/** Format with a timestamp and the level, colorized with ANSI escape codes */
|
|
91
|
-
readonly ansi_level: (this: void, entry: Entry) => string;
|
|
91
|
+
readonly ansi_level: (this: void, entry: Entry) => string[];
|
|
92
92
|
/**
|
|
93
93
|
* Format with a timestamp and colorize the message with ANSI escape codes.
|
|
94
94
|
* For EMERG and ALERT, the levels are included
|
|
95
95
|
*/
|
|
96
96
|
readonly ansi_message: (this: void, entry: Entry) => string;
|
|
97
|
-
|
|
97
|
+
readonly css_level: (this: void, entry: Entry) => string[];
|
|
98
|
+
readonly css_message: (this: void, entry: Entry) => string[];
|
|
98
99
|
readonly default: (this: void, entry: Entry) => string;
|
|
99
100
|
};
|
|
100
|
-
export declare function format(entry: Entry): string;
|
|
101
|
+
export declare function format(entry: Entry): string[];
|
|
101
102
|
/** Whether log entries are being recorded */
|
|
102
103
|
export declare let isEnabled: boolean;
|
|
103
104
|
export interface LogConfiguration {
|
|
@@ -115,12 +116,12 @@ export interface LogConfiguration {
|
|
|
115
116
|
* Formats a log entry into a string
|
|
116
117
|
* @default `[${ms / 1000}] ${message}`
|
|
117
118
|
*/
|
|
118
|
-
format?(this: void, entry: Entry): string;
|
|
119
|
+
format?(this: void, entry: Entry): string | string[];
|
|
119
120
|
/**
|
|
120
121
|
* Outputs a log message
|
|
121
122
|
* @default console.error()
|
|
122
123
|
*/
|
|
123
|
-
output?(this: void, message: string): unknown;
|
|
124
|
+
output?(this: void, ...message: string[]): unknown;
|
|
124
125
|
/**
|
|
125
126
|
* If set, output() all current entries after `configure` is done
|
|
126
127
|
* @default false
|
package/dist/internal/log.js
CHANGED
|
@@ -97,9 +97,16 @@ export function log_deprecated(symbol) {
|
|
|
97
97
|
function ansi(text, format) {
|
|
98
98
|
return `\x1b[${format}m${text}\x1b[0m`;
|
|
99
99
|
}
|
|
100
|
-
function _prettyMs(entry,
|
|
100
|
+
function _prettyMs(entry, style) {
|
|
101
101
|
const text = '[' + (entry.elapsedMs / 1000).toFixed(3).padStart(10) + '] ';
|
|
102
|
-
|
|
102
|
+
switch (style) {
|
|
103
|
+
case 'ansi':
|
|
104
|
+
return ansi(text, '2;37');
|
|
105
|
+
case 'css':
|
|
106
|
+
return ['%c' + text, 'opacity: 0.8; color: white;'];
|
|
107
|
+
default:
|
|
108
|
+
return text;
|
|
109
|
+
}
|
|
103
110
|
}
|
|
104
111
|
const _ansiLevelColor = {
|
|
105
112
|
[Level.EMERG]: '1;4;37;41',
|
|
@@ -121,6 +128,26 @@ const _ansiMessageColor = {
|
|
|
121
128
|
[Level.INFO]: '37',
|
|
122
129
|
[Level.DEBUG]: '2;37',
|
|
123
130
|
};
|
|
131
|
+
const _cssLevelColor = {
|
|
132
|
+
[Level.EMERG]: 'font-weight: bold; text-decoration: underline; color: white; background-color: red;',
|
|
133
|
+
[Level.ALERT]: 'font-weight: bold; color: white; background-color: red;',
|
|
134
|
+
[Level.CRIT]: 'font-weight: bold; color: magenta;',
|
|
135
|
+
[Level.ERR]: 'font-weight: bold; color: red;',
|
|
136
|
+
[Level.WARN]: 'font-weight: bold; color: yellow;',
|
|
137
|
+
[Level.NOTICE]: 'font-weight: bold; color: cyan;',
|
|
138
|
+
[Level.INFO]: 'font-weight: bold; color: white;',
|
|
139
|
+
[Level.DEBUG]: 'opacity: 0.8; color: white;',
|
|
140
|
+
};
|
|
141
|
+
const _cssMessageColor = {
|
|
142
|
+
[Level.EMERG]: 'font-weight: bold; color: red;',
|
|
143
|
+
[Level.ALERT]: 'font-weight: bold; color: red;',
|
|
144
|
+
[Level.CRIT]: 'font-weight: bold; color: red;',
|
|
145
|
+
[Level.ERR]: 'color: red;',
|
|
146
|
+
[Level.WARN]: 'color: yellow;',
|
|
147
|
+
[Level.NOTICE]: 'font-weight: bold; color: white;',
|
|
148
|
+
[Level.INFO]: 'color: white;',
|
|
149
|
+
[Level.DEBUG]: 'opacity: 0.8; color: white;',
|
|
150
|
+
};
|
|
124
151
|
/**
|
|
125
152
|
* Various format functions included to make using the logger easier.
|
|
126
153
|
* These are not the only formats you can use.
|
|
@@ -129,34 +156,48 @@ export const formats = {
|
|
|
129
156
|
/** Format with a timestamp and the level, colorized with ANSI escape codes */
|
|
130
157
|
ansi_level(entry) {
|
|
131
158
|
const levelText = ansi(levels[entry.level].toUpperCase(), _ansiLevelColor[entry.level]);
|
|
132
|
-
return [_prettyMs(entry,
|
|
159
|
+
return [_prettyMs(entry, 'ansi'), levelText, entry.message];
|
|
133
160
|
},
|
|
134
161
|
/**
|
|
135
162
|
* Format with a timestamp and colorize the message with ANSI escape codes.
|
|
136
163
|
* For EMERG and ALERT, the levels are included
|
|
137
164
|
*/
|
|
138
165
|
ansi_message(entry) {
|
|
139
|
-
let msg = _prettyMs(entry,
|
|
166
|
+
let msg = _prettyMs(entry, 'ansi');
|
|
140
167
|
const isImportant = entry.level < Level.CRIT;
|
|
141
168
|
if (isImportant)
|
|
142
169
|
msg += ansi(levels[entry.level].toUpperCase(), _ansiLevelColor[entry.level]) + ': ';
|
|
143
170
|
msg += ansi(entry.message, _ansiMessageColor[entry.level]);
|
|
144
171
|
return msg;
|
|
145
172
|
},
|
|
146
|
-
|
|
173
|
+
css_level(entry) {
|
|
174
|
+
const levelLabel = levels[entry.level].toUpperCase();
|
|
175
|
+
return [..._prettyMs(entry, 'css'), `%c${levelLabel}%c ${entry.message}`, _cssLevelColor[entry.level], ''];
|
|
176
|
+
},
|
|
177
|
+
css_message(entry) {
|
|
178
|
+
const text = _prettyMs(entry, 'css');
|
|
179
|
+
const isImportant = entry.level < Level.CRIT;
|
|
180
|
+
if (isImportant) {
|
|
181
|
+
const levelLabel = levels[entry.level].toUpperCase();
|
|
182
|
+
text.push(`%c${levelLabel}%c:`, _cssLevelColor[entry.level], '');
|
|
183
|
+
}
|
|
184
|
+
text.push('%c' + entry.message, _cssMessageColor[entry.level]);
|
|
185
|
+
return text;
|
|
186
|
+
},
|
|
147
187
|
default(entry) {
|
|
148
188
|
return `[${_prettyMs(entry)}] ${entry.message}`;
|
|
149
189
|
},
|
|
150
190
|
};
|
|
151
191
|
let _format = formats.default;
|
|
152
192
|
export function format(entry) {
|
|
153
|
-
|
|
193
|
+
const formatted = _format(entry);
|
|
194
|
+
return Array.isArray(formatted) ? formatted : [formatted];
|
|
154
195
|
}
|
|
155
196
|
let _output = console.error;
|
|
156
197
|
function output(entry) {
|
|
157
198
|
if (entry.level > minLevel)
|
|
158
199
|
return;
|
|
159
|
-
_output(format(entry));
|
|
200
|
+
_output(...format(entry));
|
|
160
201
|
}
|
|
161
202
|
let minLevel = Level.ALERT;
|
|
162
203
|
// Configuration
|
package/dist/mixins/async.js
CHANGED
|
@@ -50,10 +50,11 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
50
50
|
var e = new Error(message);
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
|
+
import { getAllPrototypes } from 'utilium';
|
|
53
54
|
import { StoreFS } from '../backends/store/fs.js';
|
|
54
55
|
import { Errno, ErrnoError } from '../internal/error.js';
|
|
55
56
|
import { LazyFile, parseFlag } from '../internal/file.js';
|
|
56
|
-
import { crit,
|
|
57
|
+
import { crit, debug, err } from '../internal/log.js';
|
|
57
58
|
import { join } from '../vfs/path.js';
|
|
58
59
|
/**
|
|
59
60
|
* Async() implements synchronous methods on an asynchronous file system
|
|
@@ -80,6 +81,8 @@ export function Async(FS) {
|
|
|
80
81
|
super(...args);
|
|
81
82
|
this._promise = Promise.resolve();
|
|
82
83
|
this._isInitialized = false;
|
|
84
|
+
/** Tracks how many updates to the sync. cache we skipped during initialization */
|
|
85
|
+
this._skippedCacheUpdates = 0;
|
|
83
86
|
this._patchAsync();
|
|
84
87
|
}
|
|
85
88
|
async ready() {
|
|
@@ -103,6 +106,7 @@ export function Async(FS) {
|
|
|
103
106
|
}
|
|
104
107
|
try {
|
|
105
108
|
await this.crossCopy('/');
|
|
109
|
+
debug(`Skipped ${this._skippedCacheUpdates} updates to the sync cache during initialization`);
|
|
106
110
|
this._isInitialized = true;
|
|
107
111
|
}
|
|
108
112
|
catch (e) {
|
|
@@ -131,9 +135,9 @@ export function Async(FS) {
|
|
|
131
135
|
}
|
|
132
136
|
createFileSync(path, flag, mode, options) {
|
|
133
137
|
this.checkSync(path, 'createFile');
|
|
134
|
-
this._sync.createFileSync(path, flag, mode, options);
|
|
138
|
+
const file = this._sync.createFileSync(path, flag, mode, options);
|
|
135
139
|
this._async(this.createFile(path, flag, mode, options));
|
|
136
|
-
return this
|
|
140
|
+
return new LazyFile(this, path, flag, file.statSync());
|
|
137
141
|
}
|
|
138
142
|
openFileSync(path, flag) {
|
|
139
143
|
this.checkSync(path, 'openFile');
|
|
@@ -220,38 +224,30 @@ export function Async(FS) {
|
|
|
220
224
|
}
|
|
221
225
|
/**
|
|
222
226
|
* @internal
|
|
223
|
-
* Patch all async methods to also call their synchronous counterparts unless called from
|
|
227
|
+
* Patch all async methods to also call their synchronous counterparts unless called from themselves (either sync or async)
|
|
224
228
|
*/
|
|
225
229
|
_patchAsync() {
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
'
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
'rmdir',
|
|
233
|
-
'mkdir',
|
|
234
|
-
'readdir',
|
|
235
|
-
'link',
|
|
236
|
-
'sync',
|
|
237
|
-
'exists',
|
|
238
|
-
];
|
|
239
|
-
for (const key of asyncFSMethodKeys) {
|
|
240
|
-
if (typeof this[key] !== 'function')
|
|
241
|
-
continue;
|
|
230
|
+
const methods = Array.from(getAllPrototypes(this))
|
|
231
|
+
.flatMap(Object.getOwnPropertyNames)
|
|
232
|
+
.filter(key => typeof this[key] == 'function' && `${key}Sync` in this);
|
|
233
|
+
debug('Async: patching methods: ' + methods.join(', '));
|
|
234
|
+
for (const key of methods) {
|
|
235
|
+
// TS does not narrow the union based on the key
|
|
242
236
|
const originalMethod = this[key];
|
|
243
237
|
this[key] = async (...args) => {
|
|
244
|
-
var _a, _b;
|
|
238
|
+
var _a, _b, _c;
|
|
245
239
|
const result = await originalMethod.apply(this, args);
|
|
246
|
-
|
|
240
|
+
const stack = (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(2).join('\n');
|
|
241
|
+
// !stack == From the async queue
|
|
242
|
+
if ((stack === null || stack === void 0 ? void 0 : stack.includes(`at <computed> [as ${key}]`)) || (stack === null || stack === void 0 ? void 0 : stack.includes(`${key}Sync `)) || !stack)
|
|
247
243
|
return result;
|
|
248
244
|
if (!this._isInitialized) {
|
|
249
|
-
|
|
245
|
+
this._skippedCacheUpdates++;
|
|
250
246
|
return result;
|
|
251
247
|
}
|
|
252
248
|
try {
|
|
253
|
-
// @ts-expect-error 2556
|
|
254
|
-
(
|
|
249
|
+
// @ts-expect-error 2556 - The type of `args` is not narrowed
|
|
250
|
+
(_c = (_b = this._sync) === null || _b === void 0 ? void 0 : _b[`${key}Sync`]) === null || _c === void 0 ? void 0 : _c.call(_b, ...args);
|
|
255
251
|
}
|
|
256
252
|
catch (e) {
|
|
257
253
|
throw err(new ErrnoError(e.errno, e.message + ' (Out of sync!)', e.path, key), { fs: this });
|
package/dist/mixins/shared.d.ts
CHANGED
|
@@ -8,12 +8,12 @@ import type { FileSystem } from '../internal/filesystem.js';
|
|
|
8
8
|
export type Mixin<TBase extends typeof FileSystem, TMixin> = (abstract new (...args: any[]) => TMixin) & TBase;
|
|
9
9
|
/**
|
|
10
10
|
* @internal @hidden
|
|
11
|
-
* Note this
|
|
11
|
+
* Note this includes `existsSync`, even though it is a concrete method.
|
|
12
12
|
*/
|
|
13
13
|
export type _SyncFSKeys = Exclude<Extract<keyof FileSystem, `${string}Sync`>, '_disableSync'>;
|
|
14
14
|
/**
|
|
15
15
|
* @internal @hidden
|
|
16
|
-
* Note this
|
|
16
|
+
* Note this includes `exists`, even though it is a concrete method.
|
|
17
17
|
*/
|
|
18
18
|
export type _AsyncFSKeys = {
|
|
19
19
|
[K in _SyncFSKeys]: K extends `${infer T}Sync` ? T : never;
|
package/dist/polyfills.d.ts
CHANGED
package/dist/polyfills.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
1
2
|
var _a, _b, _c;
|
|
3
|
+
import { warn } from './internal/log.js';
|
|
2
4
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
3
|
-
(_a = Promise.withResolvers) !== null && _a !== void 0 ? _a : (Promise.withResolvers =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
5
|
+
(_a = Promise.withResolvers) !== null && _a !== void 0 ? _a : (Promise.withResolvers = (warn('Using a polyfill of Promise.withResolvers'),
|
|
6
|
+
function () {
|
|
7
|
+
let _resolve,
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
|
+
_reject;
|
|
10
|
+
const promise = new Promise((resolve, reject) => {
|
|
11
|
+
_resolve = resolve;
|
|
12
|
+
_reject = reject;
|
|
13
|
+
});
|
|
14
|
+
return { promise, resolve: _resolve, reject: _reject };
|
|
15
|
+
}));
|
|
13
16
|
// @ts-expect-error 2540
|
|
14
|
-
(_b = Symbol['dispose']) !== null && _b !== void 0 ? _b : (Symbol['dispose'] = Symbol('Symbol.dispose'));
|
|
17
|
+
(_b = Symbol['dispose']) !== null && _b !== void 0 ? _b : (Symbol['dispose'] = (warn('Using a polyfill of Symbol.dispose'), Symbol('Symbol.dispose')));
|
|
15
18
|
// @ts-expect-error 2540
|
|
16
|
-
(_c = Symbol['asyncDispose']) !== null && _c !== void 0 ? _c : (Symbol['asyncDispose'] = Symbol('Symbol.asyncDispose'));
|
|
17
|
-
|
|
19
|
+
(_c = Symbol['asyncDispose']) !== null && _c !== void 0 ? _c : (Symbol['asyncDispose'] = (warn('Using a polyfill of Symbol.asyncDispose'), Symbol('Symbol.asyncDispose')));
|
|
20
|
+
/* node:coverage enable */
|
package/dist/vfs/async.js
CHANGED
|
@@ -166,7 +166,7 @@ export function write(fd, data, cbPosOff, cbLenEnc, cbPosEnc, cb = nop) {
|
|
|
166
166
|
default:
|
|
167
167
|
// ...try to find the callback and get out of here!
|
|
168
168
|
cb = (typeof cbLenEnc === 'function' ? cbLenEnc : typeof cbPosEnc === 'function' ? cbPosEnc : cb);
|
|
169
|
-
cb(new ErrnoError(Errno.EINVAL, 'Invalid arguments
|
|
169
|
+
cb(new ErrnoError(Errno.EINVAL, 'Invalid arguments'));
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
172
|
buffer = Buffer.from(data);
|
|
@@ -421,29 +421,43 @@ watch;
|
|
|
421
421
|
* @returns A ReadStream object for interacting with the file's contents.
|
|
422
422
|
*/
|
|
423
423
|
export function createReadStream(path, options) {
|
|
424
|
-
|
|
424
|
+
var _a;
|
|
425
425
|
options = typeof options == 'object' ? options : { encoding: options };
|
|
426
|
+
const _handle = promises.open.call(this, path, 'r', options === null || options === void 0 ? void 0 : options.mode);
|
|
427
|
+
void _handle.then(handle => {
|
|
428
|
+
if (typeof options.start == 'number')
|
|
429
|
+
handle.file.position = options.start;
|
|
430
|
+
});
|
|
426
431
|
let handle;
|
|
427
432
|
const stream = new ReadStream({
|
|
428
|
-
highWaterMark: options.highWaterMark ||
|
|
429
|
-
encoding: options.encoding
|
|
433
|
+
highWaterMark: options.highWaterMark || 0x1000,
|
|
434
|
+
encoding: (_a = options.encoding) !== null && _a !== void 0 ? _a : undefined,
|
|
430
435
|
async read(size) {
|
|
436
|
+
var _a;
|
|
431
437
|
try {
|
|
432
|
-
handle || (handle = await
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (!result.bytesRead) {
|
|
438
|
+
handle || (handle = await _handle);
|
|
439
|
+
const start = (_a = options.start) !== null && _a !== void 0 ? _a : handle.file.position;
|
|
440
|
+
if (typeof options.end === 'number' && start >= options.end) {
|
|
441
|
+
stream.push(null);
|
|
437
442
|
await handle.close();
|
|
443
|
+
return;
|
|
438
444
|
}
|
|
445
|
+
if (typeof options.end === 'number') {
|
|
446
|
+
size = Math.min(size, options.end - start);
|
|
447
|
+
}
|
|
448
|
+
const result = await handle.read(new Uint8Array(size), 0, size);
|
|
449
|
+
stream.push(!result.bytesRead ? null : result.buffer.subarray(0, result.bytesRead));
|
|
450
|
+
if (!result.bytesRead)
|
|
451
|
+
await handle.close();
|
|
439
452
|
}
|
|
440
453
|
catch (error) {
|
|
441
454
|
await (handle === null || handle === void 0 ? void 0 : handle.close());
|
|
442
455
|
stream.destroy(error);
|
|
443
456
|
}
|
|
444
457
|
},
|
|
445
|
-
destroy(error, callback) {
|
|
446
|
-
handle === null || handle === void 0 ? void 0 : handle.close().
|
|
458
|
+
async destroy(error, callback) {
|
|
459
|
+
await (handle === null || handle === void 0 ? void 0 : handle.close().catch(nop));
|
|
460
|
+
callback(error);
|
|
447
461
|
},
|
|
448
462
|
});
|
|
449
463
|
stream.path = path.toString();
|
|
@@ -458,28 +472,37 @@ createReadStream;
|
|
|
458
472
|
* @returns A WriteStream object for writing to the file.
|
|
459
473
|
*/
|
|
460
474
|
export function createWriteStream(path, options) {
|
|
461
|
-
const context = this;
|
|
462
475
|
options = typeof options == 'object' ? options : { encoding: options };
|
|
476
|
+
const _handle = promises.open.call(this, path, 'w', options === null || options === void 0 ? void 0 : options.mode);
|
|
477
|
+
void _handle.then(handle => {
|
|
478
|
+
if (typeof options.start == 'number')
|
|
479
|
+
handle.file.position = options.start;
|
|
480
|
+
});
|
|
463
481
|
let handle;
|
|
482
|
+
const { stack } = new Error();
|
|
464
483
|
const stream = new WriteStream({
|
|
465
484
|
highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark,
|
|
466
485
|
async write(chunk, encoding, callback) {
|
|
467
486
|
try {
|
|
468
|
-
handle || (handle = await
|
|
469
|
-
await handle.write(chunk,
|
|
470
|
-
|
|
487
|
+
handle || (handle = await _handle);
|
|
488
|
+
const { bytesWritten } = await handle.write(chunk, null, encoding);
|
|
489
|
+
if (bytesWritten == chunk.length)
|
|
490
|
+
return callback();
|
|
491
|
+
throw new ErrnoError(Errno.EIO, `Failed to write full chunk of write stream (wrote ${bytesWritten}/${chunk.length} bytes)`, handle.file.path);
|
|
471
492
|
}
|
|
472
493
|
catch (error) {
|
|
473
494
|
await (handle === null || handle === void 0 ? void 0 : handle.close());
|
|
495
|
+
error.stack += stack === null || stack === void 0 ? void 0 : stack.slice(5);
|
|
474
496
|
callback(error);
|
|
475
497
|
}
|
|
476
498
|
},
|
|
477
|
-
destroy(error, callback) {
|
|
499
|
+
async destroy(error, callback) {
|
|
500
|
+
await (handle === null || handle === void 0 ? void 0 : handle.close().catch(callback));
|
|
478
501
|
callback(error);
|
|
479
|
-
void (handle === null || handle === void 0 ? void 0 : handle.close().then(() => callback(error)).catch(callback));
|
|
480
502
|
},
|
|
481
|
-
final(callback) {
|
|
482
|
-
|
|
503
|
+
async final(callback) {
|
|
504
|
+
await (handle === null || handle === void 0 ? void 0 : handle.close().catch(nop));
|
|
505
|
+
callback();
|
|
483
506
|
},
|
|
484
507
|
});
|
|
485
508
|
stream.path = path.toString();
|
package/dist/vfs/promises.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
2
|
import type * as promises from 'node:fs/promises';
|
|
3
3
|
import type { Stream } from 'node:stream';
|
|
4
|
-
import type { ReadableStream as TReadableStream } from 'node:stream/web';
|
|
5
4
|
import type { Interface as ReadlineInterface } from 'readline';
|
|
6
5
|
import type { V_Context } from '../context.js';
|
|
7
6
|
import type { File } from '../internal/file.js';
|
|
@@ -86,15 +85,10 @@ export declare class FileHandle implements promises.FileHandle {
|
|
|
86
85
|
}): Promise<Buffer>;
|
|
87
86
|
readFile(_options: (fs.ObjectEncodingOptions & promises.FlagAndOpenMode) | BufferEncoding): Promise<string>;
|
|
88
87
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* An error will be thrown if this method is called more than once or is called after the `FileHandle` is closed or closing.
|
|
92
|
-
*
|
|
93
|
-
* While the `ReadableStream` will read the file to completion,
|
|
94
|
-
* it will not close the `FileHandle` automatically.
|
|
95
|
-
* User code must still call the `fileHandle.close()` method.
|
|
88
|
+
* Read file data using a `ReadableStream`.
|
|
89
|
+
* The handle will not be closed automatically.
|
|
96
90
|
*/
|
|
97
|
-
readableWebStream(options?: promises.ReadableWebStreamOptions):
|
|
91
|
+
readableWebStream(options?: promises.ReadableWebStreamOptions): ReadableStream<Uint8Array>;
|
|
98
92
|
/**
|
|
99
93
|
* @todo Implement
|
|
100
94
|
*/
|
|
@@ -111,7 +105,7 @@ export declare class FileHandle implements promises.FileHandle {
|
|
|
111
105
|
* Asynchronously writes `string` to the file.
|
|
112
106
|
* The `FileHandle` must have been opened for writing.
|
|
113
107
|
* It is unsafe to call `write()` multiple times on the same file without waiting for the `Promise`
|
|
114
|
-
* to be resolved (or rejected). For this scenario, `
|
|
108
|
+
* to be resolved (or rejected). For this scenario, `createWriteStream` is strongly recommended.
|
|
115
109
|
*/
|
|
116
110
|
write<T extends FileContents>(data: T, options?: number | null | {
|
|
117
111
|
offset?: number;
|
|
@@ -296,9 +290,9 @@ export declare function lutimes(this: V_Context, path: fs.PathLike, atime: fs.Ti
|
|
|
296
290
|
*/
|
|
297
291
|
export declare function realpath(this: V_Context, path: fs.PathLike, options: fs.BufferEncodingOption): Promise<Buffer>;
|
|
298
292
|
export declare function realpath(this: V_Context, path: fs.PathLike, options?: fs.EncodingOption | BufferEncoding): Promise<string>;
|
|
299
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | BufferEncoding):
|
|
300
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options: fs.WatchOptions | fs.BufferEncodingOption):
|
|
301
|
-
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | string):
|
|
293
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | BufferEncoding): AsyncIteratorObject<promises.FileChangeInfo<string>>;
|
|
294
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options: fs.WatchOptions | fs.BufferEncodingOption): AsyncIteratorObject<promises.FileChangeInfo<Buffer>>;
|
|
295
|
+
export declare function watch(this: V_Context, filename: fs.PathLike, options?: fs.WatchOptions | string): AsyncIteratorObject<promises.FileChangeInfo<string>> | AsyncIteratorObject<promises.FileChangeInfo<Buffer>>;
|
|
302
296
|
export declare function access(this: V_Context, path: fs.PathLike, mode?: number): Promise<void>;
|
|
303
297
|
/**
|
|
304
298
|
* Asynchronous `rm`. Removes files or directories (recursively).
|