|
4 | 4 | // See https://github.com/libuv/libuv/pull/1501.
|
5 | 5 | const kIoMaxLength = 2 ** 31 - 1;
|
6 | 6 |
|
7 |
| -// Note: This is different from kReadFileBufferLength used for non-promisified |
8 |
| -// fs.readFile. |
9 |
| -const kReadFileMaxChunkSize = 2 ** 14; |
| 7 | +const kReadFileBufferLength = 512 * 1024; |
| 8 | +const kReadFileUnknownBufferLength = 64 * 1024; |
10 | 9 | const kWriteFileMaxChunkSize = 2 ** 14;
|
11 | 10 |
|
12 | 11 | const {
|
@@ -316,25 +315,46 @@ async function readFileHandle(filehandle, options) {
|
316 | 315 | if (size > kIoMaxLength)
|
317 | 316 | throw new ERR_FS_FILE_TOO_LARGE(size);
|
318 | 317 |
|
319 |
| - const chunks = []; |
320 |
| - let isFirstChunk = true; |
321 |
| - const firstChunkSize = size === 0 ? kReadFileMaxChunkSize : size; |
322 |
| - const chunkSize = MathMin(firstChunkSize, kReadFileMaxChunkSize); |
323 | 318 | let endOfFile = false;
|
| 319 | + let totalRead = 0; |
| 320 | + const noSize = size === 0; |
| 321 | + const buffers = []; |
| 322 | + const fullBuffer = noSize ? undefined : Buffer.allocUnsafeSlow(size); |
324 | 323 | do {
|
325 | 324 | if (signal?.aborted) {
|
326 | 325 | throw lazyDOMException('The operation was aborted', 'AbortError');
|
327 | 326 | }
|
328 |
| - const buf = Buffer.alloc(isFirstChunk ? firstChunkSize : chunkSize); |
329 |
| - const { bytesRead, buffer } = |
330 |
| - await read(filehandle, buf, 0, buf.length, -1); |
331 |
| - endOfFile = bytesRead === 0; |
332 |
| - if (bytesRead > 0) |
333 |
| - ArrayPrototypePush(chunks, buffer.slice(0, bytesRead)); |
334 |
| - isFirstChunk = false; |
| 327 | + let buffer; |
| 328 | + let offset; |
| 329 | + let length; |
| 330 | + if (noSize) { |
| 331 | + buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength); |
| 332 | + offset = 0; |
| 333 | + length = kReadFileUnknownBufferLength; |
| 334 | + } else { |
| 335 | + buffer = fullBuffer; |
| 336 | + offset = totalRead; |
| 337 | + length = MathMin(size - totalRead, kReadFileBufferLength); |
| 338 | + } |
| 339 | + |
| 340 | + const bytesRead = (await binding.read(filehandle.fd, buffer, offset, |
| 341 | + length, -1, kUsePromises)) || 0; |
| 342 | + totalRead += bytesRead; |
| 343 | + endOfFile = bytesRead === 0 || totalRead === size; |
| 344 | + if (noSize && bytesRead > 0) { |
| 345 | + const isBufferFull = bytesRead === kReadFileUnknownBufferLength; |
| 346 | + const chunkBuffer = isBufferFull ? buffer : buffer.slice(0, bytesRead); |
| 347 | + ArrayPrototypePush(buffers, chunkBuffer); |
| 348 | + } |
335 | 349 | } while (!endOfFile);
|
336 | 350 |
|
337 |
| - const result = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks); |
| 351 | + let result; |
| 352 | + if (size > 0) { |
| 353 | + result = totalRead === size ? fullBuffer : fullBuffer.slice(0, totalRead); |
| 354 | + } else { |
| 355 | + result = buffers.length === 1 ? buffers[0] : Buffer.concat(buffers, |
| 356 | + totalRead); |
| 357 | + } |
338 | 358 |
|
339 | 359 | return options.encoding ? result.toString(options.encoding) : result;
|
340 | 360 | }
|
|
0 commit comments