@zenfs/core 0.12.4 → 0.12.6
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/browser.min.js +3 -3
- package/dist/browser.min.js.map +3 -3
- package/dist/emulation/dir.d.ts +1 -0
- package/dist/emulation/dir.js +3 -0
- package/dist/emulation/watchers.d.ts +27 -0
- package/dist/emulation/watchers.js +38 -0
- package/dist/file.d.ts +3 -0
- package/dist/file.js +82 -63
- package/package.json +4 -3
- package/src/emulation/dir.ts +4 -0
- package/src/emulation/watchers.ts +57 -0
- package/src/file.ts +85 -68
package/dist/emulation/dir.d.ts
CHANGED
package/dist/emulation/dir.js
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
4
|
+
import { EventEmitter } from 'eventemitter3';
|
|
5
|
+
import type { EventEmitter as NodeEventEmitter } from 'node:events';
|
|
6
|
+
import type * as fs from 'node:fs';
|
|
7
|
+
declare class Watcher<TEvents extends Record<string, unknown[]> = Record<string, unknown[]>> extends EventEmitter<TEvents> implements NodeEventEmitter {
|
|
8
|
+
off<T extends EventEmitter.EventNames<TEvents>>(event: T, fn?: ((...args: any[]) => void) | undefined, context?: any, once?: boolean | undefined): this;
|
|
9
|
+
removeListener<T extends EventEmitter.EventNames<TEvents>>(event: T, fn?: ((...args: any[]) => void) | undefined, context?: any, once?: boolean | undefined): this;
|
|
10
|
+
setMaxListeners(): never;
|
|
11
|
+
getMaxListeners(): never;
|
|
12
|
+
prependListener(): never;
|
|
13
|
+
prependOnceListener(): never;
|
|
14
|
+
rawListeners(): never;
|
|
15
|
+
ref(): this;
|
|
16
|
+
unref(): this;
|
|
17
|
+
}
|
|
18
|
+
export declare class FSWatcher extends Watcher<{
|
|
19
|
+
change: [eventType: string, filename: string | Buffer];
|
|
20
|
+
close: [];
|
|
21
|
+
error: [error: Error];
|
|
22
|
+
}> implements fs.FSWatcher {
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare class StatWatcher extends Watcher implements fs.StatWatcher {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { EventEmitter } from 'eventemitter3';
|
|
2
|
+
import { ErrnoError } from '../error.js';
|
|
3
|
+
class Watcher extends EventEmitter {
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
+
off(event, fn, context, once) {
|
|
6
|
+
return super.off(event, fn, context, once);
|
|
7
|
+
}
|
|
8
|
+
removeListener(event, fn, context, once) {
|
|
9
|
+
return super.removeListener(event, fn, context, once);
|
|
10
|
+
}
|
|
11
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
12
|
+
setMaxListeners() {
|
|
13
|
+
throw ErrnoError.With('ENOTSUP');
|
|
14
|
+
}
|
|
15
|
+
getMaxListeners() {
|
|
16
|
+
throw ErrnoError.With('ENOTSUP');
|
|
17
|
+
}
|
|
18
|
+
prependListener() {
|
|
19
|
+
throw ErrnoError.With('ENOTSUP');
|
|
20
|
+
}
|
|
21
|
+
prependOnceListener() {
|
|
22
|
+
throw ErrnoError.With('ENOTSUP');
|
|
23
|
+
}
|
|
24
|
+
rawListeners() {
|
|
25
|
+
throw ErrnoError.With('ENOTSUP');
|
|
26
|
+
}
|
|
27
|
+
ref() {
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
unref() {
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class FSWatcher extends Watcher {
|
|
35
|
+
close() { }
|
|
36
|
+
}
|
|
37
|
+
export class StatWatcher extends Watcher {
|
|
38
|
+
}
|
package/dist/file.d.ts
CHANGED
|
@@ -246,6 +246,7 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
246
246
|
* Synchronous `stat`.
|
|
247
247
|
*/
|
|
248
248
|
statSync(): Stats;
|
|
249
|
+
protected _truncate(length: number): void;
|
|
249
250
|
/**
|
|
250
251
|
* Asynchronous truncate.
|
|
251
252
|
* @param length
|
|
@@ -256,6 +257,7 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
256
257
|
* @param length
|
|
257
258
|
*/
|
|
258
259
|
truncateSync(length: number): void;
|
|
260
|
+
protected _write(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
|
|
259
261
|
/**
|
|
260
262
|
* Write buffer to the file.
|
|
261
263
|
* Note that it is unsafe to use fs.write multiple times on the same file
|
|
@@ -283,6 +285,7 @@ export declare class PreloadFile<FS extends FileSystem> extends File {
|
|
|
283
285
|
* @returns bytes written
|
|
284
286
|
*/
|
|
285
287
|
writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
|
|
288
|
+
protected _read(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
|
|
286
289
|
/**
|
|
287
290
|
* Read data from the file.
|
|
288
291
|
* @param buffer The buffer that the data will be
|
package/dist/file.js
CHANGED
|
@@ -236,34 +236,63 @@ export class PreloadFile extends File {
|
|
|
236
236
|
statSync() {
|
|
237
237
|
return new Stats(this.stats);
|
|
238
238
|
}
|
|
239
|
+
_truncate(length) {
|
|
240
|
+
this.dirty = true;
|
|
241
|
+
if (!isWriteable(this.flag)) {
|
|
242
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
243
|
+
}
|
|
244
|
+
this.stats.mtimeMs = Date.now();
|
|
245
|
+
if (length > this._buffer.length) {
|
|
246
|
+
const data = new Uint8Array(length - this._buffer.length);
|
|
247
|
+
// Write will set stats.size and handle syncing.
|
|
248
|
+
this.writeSync(data, 0, data.length, this._buffer.length);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.stats.size = length;
|
|
252
|
+
// Truncate.
|
|
253
|
+
this._buffer = this._buffer.slice(0, length);
|
|
254
|
+
}
|
|
239
255
|
/**
|
|
240
256
|
* Asynchronous truncate.
|
|
241
257
|
* @param length
|
|
242
258
|
*/
|
|
243
259
|
async truncate(length) {
|
|
244
|
-
this.
|
|
245
|
-
|
|
260
|
+
this._truncate(length);
|
|
261
|
+
await this.sync();
|
|
246
262
|
}
|
|
247
263
|
/**
|
|
248
264
|
* Synchronous truncate.
|
|
249
265
|
* @param length
|
|
250
266
|
*/
|
|
251
267
|
truncateSync(length) {
|
|
268
|
+
this._truncate(length);
|
|
269
|
+
this.syncSync();
|
|
270
|
+
}
|
|
271
|
+
_write(buffer, offset = 0, length = this.stats.size, position = this.position) {
|
|
252
272
|
this.dirty = true;
|
|
253
273
|
if (!isWriteable(this.flag)) {
|
|
254
274
|
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
255
275
|
}
|
|
256
|
-
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
276
|
+
const end = position + length;
|
|
277
|
+
if (end > this.stats.size) {
|
|
278
|
+
this.stats.size = end;
|
|
279
|
+
if (end > this._buffer.byteLength) {
|
|
280
|
+
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= end) {
|
|
281
|
+
this._buffer.buffer.resize(end);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
// Extend the buffer!
|
|
285
|
+
const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
|
|
286
|
+
newBuffer.set(this._buffer);
|
|
287
|
+
this._buffer = newBuffer;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
262
290
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.
|
|
266
|
-
this.
|
|
291
|
+
const slice = buffer.slice(offset, offset + length);
|
|
292
|
+
this._buffer.set(slice, position);
|
|
293
|
+
this.stats.mtimeMs = Date.now();
|
|
294
|
+
this.position = position + slice.byteLength;
|
|
295
|
+
return slice.byteLength;
|
|
267
296
|
}
|
|
268
297
|
/**
|
|
269
298
|
* Write buffer to the file.
|
|
@@ -277,8 +306,8 @@ export class PreloadFile extends File {
|
|
|
277
306
|
* data should be written. If position is null, the data will be written at
|
|
278
307
|
* the current position.
|
|
279
308
|
*/
|
|
280
|
-
async write(buffer, offset
|
|
281
|
-
const bytesWritten = this.
|
|
309
|
+
async write(buffer, offset, length, position) {
|
|
310
|
+
const bytesWritten = this._write(buffer, offset, length, position);
|
|
282
311
|
await this.sync();
|
|
283
312
|
return bytesWritten;
|
|
284
313
|
}
|
|
@@ -296,32 +325,29 @@ export class PreloadFile extends File {
|
|
|
296
325
|
* @returns bytes written
|
|
297
326
|
*/
|
|
298
327
|
writeSync(buffer, offset = 0, length = this.stats.size, position = this.position) {
|
|
299
|
-
this.
|
|
300
|
-
|
|
301
|
-
|
|
328
|
+
const bytesWritten = this._write(buffer, offset, length, position);
|
|
329
|
+
this.syncSync();
|
|
330
|
+
return bytesWritten;
|
|
331
|
+
}
|
|
332
|
+
_read(buffer, offset = 0, length = this.stats.size, position) {
|
|
333
|
+
if (!isReadable(this.flag)) {
|
|
334
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode.');
|
|
302
335
|
}
|
|
303
|
-
|
|
336
|
+
this.dirty = true;
|
|
337
|
+
position ?? (position = this.position);
|
|
338
|
+
let end = position + length;
|
|
304
339
|
if (end > this.stats.size) {
|
|
305
|
-
this.stats.size
|
|
306
|
-
if (end > this._buffer.byteLength) {
|
|
307
|
-
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= end) {
|
|
308
|
-
this._buffer.buffer.resize(end);
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
// Extend the buffer!
|
|
312
|
-
const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
|
|
313
|
-
newBuffer.set(this._buffer);
|
|
314
|
-
this._buffer = newBuffer;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
340
|
+
end = position + Math.max(this.stats.size - position, 0);
|
|
317
341
|
}
|
|
318
|
-
|
|
319
|
-
this.
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
342
|
+
this.stats.atimeMs = Date.now();
|
|
343
|
+
this._position = end;
|
|
344
|
+
const bytesRead = end - position;
|
|
345
|
+
if (bytesRead == 0) {
|
|
346
|
+
// No copy/read. Return immediatly for better performance
|
|
347
|
+
return bytesRead;
|
|
348
|
+
}
|
|
349
|
+
new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
|
|
350
|
+
return bytesRead;
|
|
325
351
|
}
|
|
326
352
|
/**
|
|
327
353
|
* Read data from the file.
|
|
@@ -334,8 +360,10 @@ export class PreloadFile extends File {
|
|
|
334
360
|
* in the file. If position is null, data will be read from the current file
|
|
335
361
|
* position.
|
|
336
362
|
*/
|
|
337
|
-
async read(buffer, offset
|
|
338
|
-
|
|
363
|
+
async read(buffer, offset, length, position) {
|
|
364
|
+
const bytesRead = this._read(buffer, offset, length, position);
|
|
365
|
+
await this.sync();
|
|
366
|
+
return { bytesRead, buffer };
|
|
339
367
|
}
|
|
340
368
|
/**
|
|
341
369
|
* Read data from the file.
|
|
@@ -348,25 +376,9 @@ export class PreloadFile extends File {
|
|
|
348
376
|
* position.
|
|
349
377
|
* @returns number of bytes written
|
|
350
378
|
*/
|
|
351
|
-
readSync(buffer, offset
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
this.dirty = true;
|
|
356
|
-
position ?? (position = this.position);
|
|
357
|
-
let end = position + length;
|
|
358
|
-
if (end > this.stats.size) {
|
|
359
|
-
end = position + Math.max(this.stats.size - position, 0);
|
|
360
|
-
}
|
|
361
|
-
this.stats.atimeMs = Date.now();
|
|
362
|
-
this._position = end;
|
|
363
|
-
const bytesRead = end - position;
|
|
364
|
-
this.syncSync();
|
|
365
|
-
if (bytesRead == 0) {
|
|
366
|
-
// No copy/read. Return immediatly for better performance
|
|
367
|
-
return bytesRead;
|
|
368
|
-
}
|
|
369
|
-
new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
|
|
379
|
+
readSync(buffer, offset, length, position) {
|
|
380
|
+
const bytesRead = this._read(buffer, offset, length, position);
|
|
381
|
+
this.statSync();
|
|
370
382
|
return bytesRead;
|
|
371
383
|
}
|
|
372
384
|
/**
|
|
@@ -374,7 +386,9 @@ export class PreloadFile extends File {
|
|
|
374
386
|
* @param mode the mode
|
|
375
387
|
*/
|
|
376
388
|
async chmod(mode) {
|
|
377
|
-
this.
|
|
389
|
+
this.dirty = true;
|
|
390
|
+
this.stats.chmod(mode);
|
|
391
|
+
await this.sync();
|
|
378
392
|
}
|
|
379
393
|
/**
|
|
380
394
|
* Synchronous `fchmod`.
|
|
@@ -391,7 +405,9 @@ export class PreloadFile extends File {
|
|
|
391
405
|
* @param gid
|
|
392
406
|
*/
|
|
393
407
|
async chown(uid, gid) {
|
|
394
|
-
this.
|
|
408
|
+
this.dirty = true;
|
|
409
|
+
this.stats.chown(uid, gid);
|
|
410
|
+
await this.sync();
|
|
395
411
|
}
|
|
396
412
|
/**
|
|
397
413
|
* Synchronous `fchown`.
|
|
@@ -404,7 +420,10 @@ export class PreloadFile extends File {
|
|
|
404
420
|
this.syncSync();
|
|
405
421
|
}
|
|
406
422
|
async utimes(atime, mtime) {
|
|
407
|
-
this.
|
|
423
|
+
this.dirty = true;
|
|
424
|
+
this.stats.atime = atime;
|
|
425
|
+
this.stats.mtime = mtime;
|
|
426
|
+
await this.sync();
|
|
408
427
|
}
|
|
409
428
|
utimesSync(atime, mtime) {
|
|
410
429
|
this.dirty = true;
|
|
@@ -412,10 +431,10 @@ export class PreloadFile extends File {
|
|
|
412
431
|
this.stats.mtime = mtime;
|
|
413
432
|
this.syncSync();
|
|
414
433
|
}
|
|
415
|
-
_setType(type) {
|
|
434
|
+
async _setType(type) {
|
|
416
435
|
this.dirty = true;
|
|
417
436
|
this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
|
|
418
|
-
|
|
437
|
+
await this.sync();
|
|
419
438
|
}
|
|
420
439
|
_setTypeSync(type) {
|
|
421
440
|
this.dirty = true;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "A filesystem in your browser",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
-
"types": "
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"filesystem",
|
|
9
9
|
"node",
|
|
@@ -46,9 +46,10 @@
|
|
|
46
46
|
"prepublishOnly": "npm run build"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@types/node": "^20.12.
|
|
49
|
+
"@types/node": "^20.12.12",
|
|
50
50
|
"@types/readable-stream": "^4.0.10",
|
|
51
51
|
"buffer": "^6.0.3",
|
|
52
|
+
"eventemitter3": "^5.0.1",
|
|
52
53
|
"minimatch": "^9.0.3",
|
|
53
54
|
"readable-stream": "^4.5.2",
|
|
54
55
|
"utilium": "^0.4.0"
|
package/src/emulation/dir.ts
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { EventEmitter } from 'eventemitter3';
|
|
2
|
+
import type { EventEmitter as NodeEventEmitter } from 'node:events';
|
|
3
|
+
import type * as fs from 'node:fs';
|
|
4
|
+
import { ErrnoError } from '../error.js';
|
|
5
|
+
|
|
6
|
+
class Watcher<TEvents extends Record<string, unknown[]> = Record<string, unknown[]>> extends EventEmitter<TEvents> implements NodeEventEmitter {
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
+
public off<T extends EventEmitter.EventNames<TEvents>>(event: T, fn?: ((...args: any[]) => void) | undefined, context?: any, once?: boolean | undefined): this {
|
|
9
|
+
return super.off<T>(event, fn as EventEmitter.EventListener<TEvents, T>, context, once);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public removeListener<T extends EventEmitter.EventNames<TEvents>>(event: T, fn?: ((...args: any[]) => void) | undefined, context?: any, once?: boolean | undefined): this {
|
|
13
|
+
return super.removeListener<T>(event, fn as EventEmitter.EventListener<TEvents, T>, context, once);
|
|
14
|
+
}
|
|
15
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
16
|
+
|
|
17
|
+
public setMaxListeners(): never {
|
|
18
|
+
throw ErrnoError.With('ENOTSUP');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public getMaxListeners(): never {
|
|
22
|
+
throw ErrnoError.With('ENOTSUP');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public prependListener(): never {
|
|
26
|
+
throw ErrnoError.With('ENOTSUP');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public prependOnceListener(): never {
|
|
30
|
+
throw ErrnoError.With('ENOTSUP');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public rawListeners(): never {
|
|
34
|
+
throw ErrnoError.With('ENOTSUP');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public ref(): this {
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public unref(): this {
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class FSWatcher
|
|
47
|
+
extends Watcher<{
|
|
48
|
+
change: [eventType: string, filename: string | Buffer];
|
|
49
|
+
close: [];
|
|
50
|
+
error: [error: Error];
|
|
51
|
+
}>
|
|
52
|
+
implements fs.FSWatcher
|
|
53
|
+
{
|
|
54
|
+
public close(): void {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class StatWatcher extends Watcher implements fs.StatWatcher {}
|
package/src/file.ts
CHANGED
|
@@ -439,13 +439,30 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
439
439
|
return new Stats(this.stats);
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
protected _truncate(length: number): void {
|
|
443
|
+
this.dirty = true;
|
|
444
|
+
if (!isWriteable(this.flag)) {
|
|
445
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
446
|
+
}
|
|
447
|
+
this.stats.mtimeMs = Date.now();
|
|
448
|
+
if (length > this._buffer.length) {
|
|
449
|
+
const data = new Uint8Array(length - this._buffer.length);
|
|
450
|
+
// Write will set stats.size and handle syncing.
|
|
451
|
+
this.writeSync(data, 0, data.length, this._buffer.length);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
this.stats.size = length;
|
|
455
|
+
// Truncate.
|
|
456
|
+
this._buffer = this._buffer.slice(0, length);
|
|
457
|
+
}
|
|
458
|
+
|
|
442
459
|
/**
|
|
443
460
|
* Asynchronous truncate.
|
|
444
461
|
* @param length
|
|
445
462
|
*/
|
|
446
463
|
public async truncate(length: number): Promise<void> {
|
|
447
|
-
this.
|
|
448
|
-
|
|
464
|
+
this._truncate(length);
|
|
465
|
+
await this.sync();
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
/**
|
|
@@ -453,21 +470,35 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
453
470
|
* @param length
|
|
454
471
|
*/
|
|
455
472
|
public truncateSync(length: number): void {
|
|
473
|
+
this._truncate(length);
|
|
474
|
+
this.syncSync();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
protected _write(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = this.position): number {
|
|
456
478
|
this.dirty = true;
|
|
457
479
|
if (!isWriteable(this.flag)) {
|
|
458
480
|
throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
|
|
459
481
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
482
|
+
const end = position + length;
|
|
483
|
+
|
|
484
|
+
if (end > this.stats.size) {
|
|
485
|
+
this.stats.size = end;
|
|
486
|
+
if (end > this._buffer.byteLength) {
|
|
487
|
+
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength! <= end) {
|
|
488
|
+
this._buffer.buffer.resize(end);
|
|
489
|
+
} else {
|
|
490
|
+
// Extend the buffer!
|
|
491
|
+
const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
|
|
492
|
+
newBuffer.set(this._buffer);
|
|
493
|
+
this._buffer = newBuffer;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
466
496
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
this.
|
|
470
|
-
this.
|
|
497
|
+
const slice = buffer.slice(offset, offset + length);
|
|
498
|
+
this._buffer.set(slice, position);
|
|
499
|
+
this.stats.mtimeMs = Date.now();
|
|
500
|
+
this.position = position + slice.byteLength;
|
|
501
|
+
return slice.byteLength;
|
|
471
502
|
}
|
|
472
503
|
|
|
473
504
|
/**
|
|
@@ -482,8 +513,8 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
482
513
|
* data should be written. If position is null, the data will be written at
|
|
483
514
|
* the current position.
|
|
484
515
|
*/
|
|
485
|
-
public async write(buffer: Uint8Array, offset
|
|
486
|
-
const bytesWritten = this.
|
|
516
|
+
public async write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number> {
|
|
517
|
+
const bytesWritten = this._write(buffer, offset, length, position);
|
|
487
518
|
await this.sync();
|
|
488
519
|
return bytesWritten;
|
|
489
520
|
}
|
|
@@ -502,32 +533,30 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
502
533
|
* @returns bytes written
|
|
503
534
|
*/
|
|
504
535
|
public writeSync(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = this.position): number {
|
|
505
|
-
this.
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const end = position + length;
|
|
536
|
+
const bytesWritten = this._write(buffer, offset, length, position);
|
|
537
|
+
this.syncSync();
|
|
538
|
+
return bytesWritten;
|
|
539
|
+
}
|
|
510
540
|
|
|
541
|
+
protected _read(buffer: ArrayBufferView, offset: number = 0, length: number = this.stats.size, position?: number): number {
|
|
542
|
+
if (!isReadable(this.flag)) {
|
|
543
|
+
throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode.');
|
|
544
|
+
}
|
|
545
|
+
this.dirty = true;
|
|
546
|
+
position ??= this.position;
|
|
547
|
+
let end = position + length;
|
|
511
548
|
if (end > this.stats.size) {
|
|
512
|
-
this.stats.size
|
|
513
|
-
if (end > this._buffer.byteLength) {
|
|
514
|
-
if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength! <= end) {
|
|
515
|
-
this._buffer.buffer.resize(end);
|
|
516
|
-
} else {
|
|
517
|
-
// Extend the buffer!
|
|
518
|
-
const newBuffer = new Uint8Array(new ArrayBuffer(end, this.fs.metadata().noResizableBuffers ? {} : { maxByteLength: size_max }));
|
|
519
|
-
newBuffer.set(this._buffer);
|
|
520
|
-
this._buffer = newBuffer;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
549
|
+
end = position + Math.max(this.stats.size - position, 0);
|
|
523
550
|
}
|
|
524
|
-
|
|
525
|
-
this.
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
551
|
+
this.stats.atimeMs = Date.now();
|
|
552
|
+
this._position = end;
|
|
553
|
+
const bytesRead = end - position;
|
|
554
|
+
if (bytesRead == 0) {
|
|
555
|
+
// No copy/read. Return immediatly for better performance
|
|
556
|
+
return bytesRead;
|
|
557
|
+
}
|
|
558
|
+
new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
|
|
559
|
+
return bytesRead;
|
|
531
560
|
}
|
|
532
561
|
|
|
533
562
|
/**
|
|
@@ -541,13 +570,10 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
541
570
|
* in the file. If position is null, data will be read from the current file
|
|
542
571
|
* position.
|
|
543
572
|
*/
|
|
544
|
-
public async read<TBuffer extends ArrayBufferView>(
|
|
545
|
-
buffer
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
position: number = 0
|
|
549
|
-
): Promise<{ bytesRead: number; buffer: TBuffer }> {
|
|
550
|
-
return { bytesRead: this.readSync(buffer, offset, length, position), buffer };
|
|
573
|
+
public async read<TBuffer extends ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{ bytesRead: number; buffer: TBuffer }> {
|
|
574
|
+
const bytesRead = this._read(buffer, offset, length, position);
|
|
575
|
+
await this.sync();
|
|
576
|
+
return { bytesRead, buffer };
|
|
551
577
|
}
|
|
552
578
|
|
|
553
579
|
/**
|
|
@@ -561,25 +587,9 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
561
587
|
* position.
|
|
562
588
|
* @returns number of bytes written
|
|
563
589
|
*/
|
|
564
|
-
public readSync(buffer: ArrayBufferView, offset
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
this.dirty = true;
|
|
569
|
-
position ??= this.position;
|
|
570
|
-
let end = position + length;
|
|
571
|
-
if (end > this.stats.size) {
|
|
572
|
-
end = position + Math.max(this.stats.size - position, 0);
|
|
573
|
-
}
|
|
574
|
-
this.stats.atimeMs = Date.now();
|
|
575
|
-
this._position = end;
|
|
576
|
-
const bytesRead = end - position;
|
|
577
|
-
this.syncSync();
|
|
578
|
-
if (bytesRead == 0) {
|
|
579
|
-
// No copy/read. Return immediatly for better performance
|
|
580
|
-
return bytesRead;
|
|
581
|
-
}
|
|
582
|
-
new Uint8Array(buffer.buffer, offset, length).set(this._buffer.slice(position, end));
|
|
590
|
+
public readSync(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number {
|
|
591
|
+
const bytesRead = this._read(buffer, offset, length, position);
|
|
592
|
+
this.statSync();
|
|
583
593
|
return bytesRead;
|
|
584
594
|
}
|
|
585
595
|
|
|
@@ -588,7 +598,9 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
588
598
|
* @param mode the mode
|
|
589
599
|
*/
|
|
590
600
|
public async chmod(mode: number): Promise<void> {
|
|
591
|
-
this.
|
|
601
|
+
this.dirty = true;
|
|
602
|
+
this.stats.chmod(mode);
|
|
603
|
+
await this.sync();
|
|
592
604
|
}
|
|
593
605
|
|
|
594
606
|
/**
|
|
@@ -607,7 +619,9 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
607
619
|
* @param gid
|
|
608
620
|
*/
|
|
609
621
|
public async chown(uid: number, gid: number): Promise<void> {
|
|
610
|
-
this.
|
|
622
|
+
this.dirty = true;
|
|
623
|
+
this.stats.chown(uid, gid);
|
|
624
|
+
await this.sync();
|
|
611
625
|
}
|
|
612
626
|
|
|
613
627
|
/**
|
|
@@ -622,7 +636,10 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
622
636
|
}
|
|
623
637
|
|
|
624
638
|
public async utimes(atime: Date, mtime: Date): Promise<void> {
|
|
625
|
-
this.
|
|
639
|
+
this.dirty = true;
|
|
640
|
+
this.stats.atime = atime;
|
|
641
|
+
this.stats.mtime = mtime;
|
|
642
|
+
await this.sync();
|
|
626
643
|
}
|
|
627
644
|
|
|
628
645
|
public utimesSync(atime: Date, mtime: Date): void {
|
|
@@ -632,10 +649,10 @@ export class PreloadFile<FS extends FileSystem> extends File {
|
|
|
632
649
|
this.syncSync();
|
|
633
650
|
}
|
|
634
651
|
|
|
635
|
-
public _setType(type: FileType): Promise<void> {
|
|
652
|
+
public async _setType(type: FileType): Promise<void> {
|
|
636
653
|
this.dirty = true;
|
|
637
654
|
this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
|
|
638
|
-
|
|
655
|
+
await this.sync();
|
|
639
656
|
}
|
|
640
657
|
|
|
641
658
|
public _setTypeSync(type: FileType): void {
|