diff --git a/src/fsa-to-node/FsaNodeFs.ts b/src/fsa-to-node/FsaNodeFs.ts index a0b5d5c4d..c080f98e6 100644 --- a/src/fsa-to-node/FsaNodeFs.ts +++ b/src/fsa-to-node/FsaNodeFs.ts @@ -34,12 +34,12 @@ import { FsaNodeDirent } from './FsaNodeDirent'; import { FLAG } from '../consts/FLAG'; import { AMODE } from '../consts/AMODE'; import { constants } from '../constants'; +import { FsaNodeStats } from './FsaNodeStats'; import type { FsCallbackApi, FsPromisesApi } from '../node/types'; import type * as misc from '../node/types/misc'; import type * as opts from '../node/types/options'; import type * as fsa from '../fsa/types'; import type { FsCommonObjects } from '../node/types/FsCommonObjects'; -import { FsaNodeStats } from './FsaNodeStats'; const notSupported: (...args: any[]) => any = () => { throw new Error('Method not supported by the File System Access API.'); @@ -105,8 +105,12 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects { const file = await dir.getFileHandle(name); return file; } catch (error) { - if (error && typeof error === 'object' && error.name === 'TypeMismatchError') - return await dir.getDirectoryHandle(name); + if (error && typeof error === 'object') { + switch (error.name) { + case 'TypeMismatchError': return await dir.getDirectoryHandle(name); + case 'NotFoundError': throw createError('ENOENT', funcName, path.join(FsaToNodeConstants.Separator)); + } + } throw error; } } @@ -316,7 +320,13 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects { const [folder, name] = pathToLocation(filename); (async () => { const handle = await this.getFileOrDir(folder, name, 'stat'); - const stats = new FsaNodeStats(bigint, handle); + let size: number = 0; + if (handle.kind === 'file') { + const file = handle; + const fileData = await file.getFile(); + size = fileData.size; + } + const stats = new FsaNodeStats(bigint, bigint ? BigInt(size) : size, handle); return stats; })().then( stats => callback(null, stats), @@ -700,7 +710,7 @@ export class FsaNodeFs implements FsCallbackApi, FsCommonObjects { public readonly X_OK = constants.X_OK; public readonly constants = constants; public readonly Dirent = FsaNodeDirent; - public readonly Stats = FsaNodeStats; + public readonly Stats = FsaNodeStats; public readonly StatFs = 0 as any; public readonly Dir = 0 as any; public readonly StatsWatcher = 0 as any; diff --git a/src/fsa-to-node/FsaNodeStats.ts b/src/fsa-to-node/FsaNodeStats.ts index a5f27a304..eafa933ff 100644 --- a/src/fsa-to-node/FsaNodeStats.ts +++ b/src/fsa-to-node/FsaNodeStats.ts @@ -26,14 +26,14 @@ export class FsaNodeStats implements misc.IStats { public readonly mode: T; public readonly nlink: T; - public constructor(isBigInt: boolean, protected readonly handle: IFileSystemHandle) { + public constructor(isBigInt: boolean, size: T, protected readonly handle: IFileSystemHandle) { const dummy = (isBigInt ? timex : time) as any as T; this.uid = dummy; this.gid = dummy; this.rdev = dummy; this.blksize = dummy; this.ino = dummy; - this.size = dummy; + this.size = size; this.blocks = dummy; this.atime = date; this.mtime = date; diff --git a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts index b9ed57ca7..316e0bda5 100644 --- a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts +++ b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts @@ -470,4 +470,27 @@ describe('.stat()', () => { const stats = await fs.promises.stat('/folder/file'); expect(stats.isFile()).toBe(true); }); + + test('can retrieve file size', async () => { + const { fs, mfs } = setup({ folder: { file: 'test' }, 'empty-folder': null, 'f.html': 'test' }); + const stats = await fs.promises.stat('/folder/file'); + expect(stats.size).toBe(4); + }); + + test('can stat a folder', async () => { + const { fs, mfs } = setup({ folder: { file: 'test' }, 'empty-folder': null, 'f.html': 'test' }); + const stats = await fs.promises.stat('/folder'); + expect(stats.isFile()).toBe(false); + expect(stats.isDirectory()).toBe(true); + }); + + test('throws on non-existing path', async () => { + const { fs, mfs } = setup({ folder: { file: 'test' }, 'empty-folder': null, 'f.html': 'test' }); + try { + const stats = await fs.promises.stat('/folder/abc'); + throw new Error('should not be here'); + } catch (error) { + expect(error.code).toBe('ENOENT'); + } + }); });