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 211 | 1x 1x 1x 1x 1x 1x 1x 1x 84x 84x 84x 84x 84x 34x 34x 95x 95x 95x 95x 64x 6x 6x 2x 4x 89x 38x 38x 37x 28x 26x 25x 25x 11x 14x 14x 9x 9x 5x 44x 44x 44x 40x 25x 6x 5x 5x 5x 5x 5x 36x 36x 36x 1x 1x 1x 1x 1x 1x 1x 1x 35x 35x 35x 34x 1x 1x 1x 34x 34x 34x 34x 19x 18x 18x 18x | import { createError, pathToFilename } from '../node/util'; import { pathToLocation } from './util'; import { ERRSTR } from '../node/constants'; import { FsaToNodeConstants } from './constants'; import { FsaNodeFsOpenFile } from './FsaNodeFsOpenFile'; import { FLAG_CON } 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'; import { isFd } from '../core/util'; 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_CON.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_CON.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); } } |