(file: string)
| 51 | * past the limit. Returns `bytes: null` for an oversize file. |
| 52 | */ |
| 53 | export async function readBoundedSource(file: string): Promise<BoundedSource> { |
| 54 | const initial = await fsp.stat(file); |
| 55 | assertRegularFile(initial); |
| 56 | if (initial.size > MAX_SOURCE_FILE_SIZE_BYTES) return { stats: initial, bytes: null }; |
| 57 | const handle = await fsp.open(file, 'r'); |
| 58 | try { |
| 59 | let stats = await handle.stat(); |
| 60 | assertRegularFile(stats); |
| 61 | if (stats.size > MAX_SOURCE_FILE_SIZE_BYTES) return { stats, bytes: null }; |
| 62 | const chunks: Buffer[] = []; |
| 63 | let size = 0; |
| 64 | while (size <= MAX_SOURCE_FILE_SIZE_BYTES) { |
| 65 | const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES, MAX_SOURCE_FILE_SIZE_BYTES + 1 - size)); |
| 66 | const { bytesRead } = await handle.read(chunk, 0, chunk.length, size); |
| 67 | if (!bytesRead) break; |
| 68 | chunks.push(chunk.subarray(0, bytesRead)); |
| 69 | size += bytesRead; |
| 70 | } |
| 71 | stats = await handle.stat(); |
| 72 | if (size > MAX_SOURCE_FILE_SIZE_BYTES || stats.size > MAX_SOURCE_FILE_SIZE_BYTES) { |
| 73 | stats.size = Math.max(size, stats.size); |
| 74 | return { stats, bytes: null }; |
| 75 | } |
| 76 | return { stats, bytes: Buffer.concat(chunks, size) }; |
| 77 | } finally { |
| 78 | await handle.close(); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | /** Synchronous {@link readBoundedSource}. */ |
| 83 | export function readBoundedSourceSync(file: string): BoundedSource { |
no test coverage detected