|
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 {
|
| 12 | + ArrayPrototypePush, |
13 | 13 | Error,
|
14 | 14 | MathMax,
|
15 | 15 | MathMin,
|
@@ -272,21 +272,43 @@ async function readFileHandle(filehandle, options) {
|
272 | 272 | if (size > kIoMaxLength)
|
273 | 273 | throw new ERR_FS_FILE_TOO_LARGE(size);
|
274 | 274 |
|
275 |
| - const chunks = []; |
276 |
| - const chunkSize = size === 0 ? |
277 |
| - kReadFileMaxChunkSize : |
278 |
| - MathMin(size, kReadFileMaxChunkSize); |
279 | 275 | let endOfFile = false;
|
| 276 | + let totalRead = 0; |
| 277 | + const noSize = size === 0; |
| 278 | + const buffers = []; |
| 279 | + const fullBuffer = noSize ? undefined : Buffer.allocUnsafeSlow(size); |
280 | 280 | do {
|
281 |
| - const buf = Buffer.alloc(chunkSize); |
282 |
| - const { bytesRead, buffer } = |
283 |
| - await read(filehandle, buf, 0, chunkSize, -1); |
284 |
| - endOfFile = bytesRead === 0; |
285 |
| - if (bytesRead > 0) |
286 |
| - chunks.push(buffer.slice(0, bytesRead)); |
| 281 | + let buffer; |
| 282 | + let offset; |
| 283 | + let length; |
| 284 | + if (noSize) { |
| 285 | + buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength); |
| 286 | + offset = 0; |
| 287 | + length = kReadFileUnknownBufferLength; |
| 288 | + } else { |
| 289 | + buffer = fullBuffer; |
| 290 | + offset = totalRead; |
| 291 | + length = MathMin(size - totalRead, kReadFileBufferLength); |
| 292 | + } |
| 293 | + |
| 294 | + const bytesRead = (await binding.read(filehandle.fd, buffer, offset, |
| 295 | + length, -1, kUsePromises)) || 0; |
| 296 | + totalRead += bytesRead; |
| 297 | + endOfFile = bytesRead === 0 || totalRead === size; |
| 298 | + if (noSize && bytesRead > 0) { |
| 299 | + const isBufferFull = bytesRead === kReadFileUnknownBufferLength; |
| 300 | + const chunkBuffer = isBufferFull ? buffer : buffer.slice(0, bytesRead); |
| 301 | + ArrayPrototypePush(buffers, chunkBuffer); |
| 302 | + } |
287 | 303 | } while (!endOfFile);
|
288 | 304 |
|
289 |
| - const result = Buffer.concat(chunks); |
| 305 | + let result; |
| 306 | + if (size > 0) { |
| 307 | + result = totalRead === size ? fullBuffer : fullBuffer.slice(0, totalRead); |
| 308 | + } else { |
| 309 | + result = buffers.length === 1 ? buffers[0] : Buffer.concat(buffers, |
| 310 | + totalRead); |
| 311 | + } |
290 | 312 |
|
291 | 313 | return options.encoding ? result.toString(options.encoding) : result;
|
292 | 314 | }
|
|
0 commit comments