mirror of
https://github.com/nodejs/node.git
synced 2025-05-14 16:35:53 +00:00

Store all primordials as properties of the primordials object. Static functions are prefixed by the constructor's name and prototype methods are prefixed by the constructor's name followed by "Prototype". For example: primordials.Object.keys becomes primordials.ObjectKeys. PR-URL: https://github.com/nodejs/node/pull/30610 Refs: https://github.com/nodejs/node/issues/29766 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
120 lines
2.9 KiB
JavaScript
120 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
MathMin,
|
|
} = primordials;
|
|
|
|
const { Buffer } = require('buffer');
|
|
|
|
const { FSReqCallback, close, read } = internalBinding('fs');
|
|
|
|
// Use 64kb in case the file type is not a regular file and thus do not know the
|
|
// actual file size. Increasing the value further results in more frequent over
|
|
// allocation for small files and consumes CPU time and memory that should be
|
|
// used else wise.
|
|
// Use up to 512kb per read otherwise to partition reading big files to prevent
|
|
// blocking other threads in case the available threads are all in use.
|
|
const kReadFileUnknownBufferLength = 64 * 1024;
|
|
const kReadFileBufferLength = 512 * 1024;
|
|
|
|
function readFileAfterRead(err, bytesRead) {
|
|
const context = this.context;
|
|
|
|
if (err)
|
|
return context.close(err);
|
|
|
|
context.pos += bytesRead;
|
|
|
|
if (context.pos === context.size || bytesRead === 0) {
|
|
context.close();
|
|
} else {
|
|
if (context.size === 0) {
|
|
// Unknown size, just read until we don't get bytes.
|
|
const buffer = bytesRead === kReadFileUnknownBufferLength ?
|
|
context.buffer : context.buffer.slice(0, bytesRead);
|
|
context.buffers.push(buffer);
|
|
}
|
|
context.read();
|
|
}
|
|
}
|
|
|
|
function readFileAfterClose(err) {
|
|
const context = this.context;
|
|
const callback = context.callback;
|
|
let buffer = null;
|
|
|
|
if (context.err || err)
|
|
return callback(context.err || err);
|
|
|
|
try {
|
|
if (context.size === 0)
|
|
buffer = Buffer.concat(context.buffers, context.pos);
|
|
else if (context.pos < context.size)
|
|
buffer = context.buffer.slice(0, context.pos);
|
|
else
|
|
buffer = context.buffer;
|
|
|
|
if (context.encoding)
|
|
buffer = buffer.toString(context.encoding);
|
|
} catch (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
callback(null, buffer);
|
|
}
|
|
|
|
class ReadFileContext {
|
|
constructor(callback, encoding) {
|
|
this.fd = undefined;
|
|
this.isUserFd = undefined;
|
|
this.size = 0;
|
|
this.callback = callback;
|
|
this.buffers = null;
|
|
this.buffer = null;
|
|
this.pos = 0;
|
|
this.encoding = encoding;
|
|
this.err = null;
|
|
}
|
|
|
|
read() {
|
|
let buffer;
|
|
let offset;
|
|
let length;
|
|
|
|
if (this.size === 0) {
|
|
buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength);
|
|
offset = 0;
|
|
length = kReadFileUnknownBufferLength;
|
|
this.buffer = buffer;
|
|
} else {
|
|
buffer = this.buffer;
|
|
offset = this.pos;
|
|
length = MathMin(kReadFileBufferLength, this.size - this.pos);
|
|
}
|
|
|
|
const req = new FSReqCallback();
|
|
req.oncomplete = readFileAfterRead;
|
|
req.context = this;
|
|
|
|
read(this.fd, buffer, offset, length, -1, req);
|
|
}
|
|
|
|
close(err) {
|
|
const req = new FSReqCallback();
|
|
req.oncomplete = readFileAfterClose;
|
|
req.context = this;
|
|
this.err = err;
|
|
|
|
if (this.isUserFd) {
|
|
process.nextTick(function tick() {
|
|
req.oncomplete(null);
|
|
});
|
|
return;
|
|
}
|
|
|
|
close(this.fd, req);
|
|
}
|
|
}
|
|
|
|
module.exports = ReadFileContext;
|