Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | 2x 2x 2x 2x 2x 2x 2x 299x 299x 299x 299x 299x 611x 611x 3564x 3564x 3564x 3564x 3247x 6x 6x 2x 4x 3558x 1181x 1181x 934x 1532x 1530x 1524x 1524x 234x 1290x 1290x 746x 746x 544x 859x 859x 859x 855x 263x 345x 5x 5x 5x 5x 5x 661x 661x 661x 283x 283x 43x 283x 283x 43x 43x 43x 618x 618x 618x 611x 7x 7x 7x 611x 611x 611x 611x 257x 256x 256x 256x | import { createError, isFd, pathToFilename } from '../node/util'; import { pathToLocation } from './util'; import { ERRSTR } from '../node/constants'; import { FsaToNodeConstants } from './constants'; import { FsaNodeFsOpenFile } from './FsaNodeFsOpenFile'; import { FLAG } from '../consts/FLAG'; import * as util from '../node/util'; import type * as fsa from '../fsa/types'; import type * as misc from '../node/types/misc'; import type { FsaNodeSyncAdapter } from './types'; export class FsaNodeCore { protected static fd: number = 0x7fffffff; protected readonly fds = new Map<number, FsaNodeFsOpenFile>(); public constructor( protected readonly root: fsa.IFileSystemDirectoryHandle | Promise<fsa.IFileSystemDirectoryHandle>, public syncAdapter?: FsaNodeSyncAdapter, ) { Iif (root instanceof Promise) { root .then(root => { (this as any).root = root; }) .catch(error => {}); } } protected getSyncAdapter(): FsaNodeSyncAdapter { const adapter = this.syncAdapter; Iif (!adapter) throw new Error('No sync adapter'); return adapter; } /** * A list of reusable (opened and closed) file descriptors, that should be * used first before creating a new file descriptor. */ releasedFds: number[] = []; protected newFdNumber(): number { const releasedFd = this.releasedFds.pop(); return typeof releasedFd === 'number' ? releasedFd : FsaNodeCore.fd--; } /** * @param path Path from root to the new folder. * @param create Whether to create the folders if they don't exist. */ protected async getDir(path: string[], create: boolean, funcName?: string): Promise<fsa.IFileSystemDirectoryHandle> { let curr: fsa.IFileSystemDirectoryHandle = await this.root; const options: fsa.GetDirectoryHandleOptions = { create }; try { for (const name of path) { curr = await curr.getDirectoryHandle(name, options); } } catch (error) { if (error && typeof error === 'object') { switch (error.name) { case 'TypeMismatchError': throw createError('ENOTDIR', funcName, path.join(FsaToNodeConstants.Separator)); case 'NotFoundError': throw createError('ENOENT', funcName, path.join(FsaToNodeConstants.Separator)); } } throw error; } return curr; } protected async getFile( path: string[], name: string, funcName?: string, create?: boolean, ): Promise<fsa.IFileSystemFileHandle> { const dir = await this.getDir(path, false, funcName); const file = await dir.getFileHandle(name, { create }); return file; } protected async getFileOrDir( path: string[], name: string, funcName?: string, ): Promise<fsa.IFileSystemFileHandle | fsa.IFileSystemDirectoryHandle> { const dir = await this.getDir(path, false, funcName); if (!name) return dir; try { const file = await dir.getFileHandle(name); return file; } catch (error) { if (error && typeof error === 'object') { switch (error.name) { case 'TypeMismatchError': try { return await dir.getDirectoryHandle(name); } catch (error2) { Iif (error2 && typeof error2 === 'object') { switch (error2.name) { case 'TypeMismatchError': throw createError('ENOTDIR', funcName, path.join(FsaToNodeConstants.Separator)); case 'NotFoundError': throw createError('ENOENT', funcName, path.join(FsaToNodeConstants.Separator)); } } } case 'NotFoundError': throw createError('ENOENT', funcName, path.join(FsaToNodeConstants.Separator)); } } throw error; } } protected getFileByFd(fd: number, funcName?: string): FsaNodeFsOpenFile { Iif (!isFd(fd)) throw TypeError(ERRSTR.FD); const file = this.fds.get(fd); if (!file) throw createError('EBADF', funcName); return file; } protected async getFileByFdAsync(fd: number, funcName?: string): Promise<FsaNodeFsOpenFile> { return this.getFileByFd(fd, funcName); } public async __getFileById(id: misc.TFileId, funcName?: string): Promise<fsa.IFileSystemFileHandle> { if (typeof id === 'number') return (await this.getFileByFd(id, funcName)).file; const filename = pathToFilename(id); const [folder, name] = pathToLocation(filename); return await this.getFile(folder, name, funcName); } protected async getFileByIdOrCreate(id: misc.TFileId, funcName?: string): Promise<fsa.IFileSystemFileHandle> { Iif (typeof id === 'number') return (await this.getFileByFd(id, funcName)).file; const filename = pathToFilename(id); const [folder, name] = pathToLocation(filename); const dir = await this.getDir(folder, false, funcName); return await dir.getFileHandle(name, { create: true }); } protected async __open(filename: string, flags: number, mode: number): Promise<FsaNodeFsOpenFile> { const [folder, name] = pathToLocation(filename); const throwIfExists = !!(flags & FLAG.O_EXCL); if (throwIfExists) { try { await this.getFile(folder, name, 'open', false); throw util.createError('EEXIST', 'writeFile'); } catch (error) { const file404 = error && typeof error === 'object' && (error.code === 'ENOENT' || error.name === 'NotFoundError'); if (!file404) { if (error && typeof error === 'object') { switch (error.name) { case 'TypeMismatchError': throw createError('ENOTDIR', 'open', filename); case 'NotFoundError': throw createError('ENOENT', 'open', filename); } } throw error; } } } try { const createIfMissing = !!(flags & FLAG.O_CREAT); const fsaFile = await this.getFile(folder, name, 'open', createIfMissing); return this.__open2(fsaFile, filename, flags, mode); } catch (error) { if (error && typeof error === 'object') { switch (error.name) { case 'TypeMismatchError': throw createError('ENOTDIR', 'open', filename); case 'NotFoundError': throw createError('ENOENT', 'open', filename); } } throw error; } } protected __open2( fsaFile: fsa.IFileSystemFileHandle, filename: string, flags: number, mode: number, ): FsaNodeFsOpenFile { const fd = this.newFdNumber(); const file = new FsaNodeFsOpenFile(fd, mode, flags, fsaFile, filename); this.fds.set(fd, file); return file; } protected async __close(fd: number): Promise<void> { const openFile = await this.getFileByFdAsync(fd, 'close'); await openFile.close(); const deleted = this.fds.delete(fd); if (deleted) this.releasedFds.push(fd); } protected getFileName(id: misc.TFileId): string { Iif (typeof id === 'number') { const openFile = this.fds.get(id); Iif (!openFile) throw createError('EBADF', 'readFile'); return openFile.filename; } return pathToFilename(id); } } |