Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fs: support BigInt in fs.*stat and fs.watchFile
Add the `bigint: true` option to all the `fs.*stat` methods and
`fs.watchFile`.
  • Loading branch information
joyeecheung committed Jun 5, 2018
commit 4ee0c9cb9e20c9690b5e6324c7c487541aed8543
56 changes: 34 additions & 22 deletions lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ function readFileAfterOpen(err, fd) {
const req = new FSReqWrap();
req.oncomplete = readFileAfterStat;
req.context = context;
binding.fstat(fd, req);
binding.fstat(fd, false, req);
}

function readFileAfterStat(err, stats) {
Expand Down Expand Up @@ -307,7 +307,7 @@ function readFile(path, options, callback) {

function tryStatSync(fd, isUserFd) {
const ctx = {};
const stats = binding.fstat(fd, undefined, ctx);
const stats = binding.fstat(fd, false, undefined, ctx);
if (ctx.errno !== undefined && !isUserFd) {
fs.closeSync(fd);
throw errors.uvException(ctx);
Expand Down Expand Up @@ -760,55 +760,67 @@ function readdirSync(path, options) {
return result;
}

function fstat(fd, callback) {
function fstat(fd, options, callback) {
if (arguments.length < 3) {
callback = options;
options = {};
}
validateUint32(fd, 'fd');
const req = new FSReqWrap();
const req = new FSReqWrap(options.bigint);
req.oncomplete = makeStatsCallback(callback);
binding.fstat(fd, req);
binding.fstat(fd, options.bigint, req);
}

function lstat(path, callback) {
function lstat(path, options, callback) {
if (arguments.length < 3) {
callback = options;
options = {};
}
callback = makeStatsCallback(callback);
path = getPathFromURL(path);
validatePath(path);
const req = new FSReqWrap();
const req = new FSReqWrap(options.bigint);
req.oncomplete = callback;
binding.lstat(pathModule.toNamespacedPath(path), req);
binding.lstat(pathModule.toNamespacedPath(path), options.bigint, req);
}

function stat(path, callback) {
function stat(path, options, callback) {
if (arguments.length < 3) {
callback = options;
options = {};
}
callback = makeStatsCallback(callback);
path = getPathFromURL(path);
validatePath(path);
const req = new FSReqWrap();
const req = new FSReqWrap(options.bigint);
req.oncomplete = callback;
binding.stat(pathModule.toNamespacedPath(path), req);
binding.stat(pathModule.toNamespacedPath(path), options.bigint, req);
}

function fstatSync(fd) {
function fstatSync(fd, options = {}) {
validateUint32(fd, 'fd');
const ctx = { fd };
const stats = binding.fstat(fd, undefined, ctx);
const stats = binding.fstat(fd, options.bigint, undefined, ctx);
handleErrorFromBinding(ctx);
return getStatsFromBinding(stats);
}

function lstatSync(path) {
function lstatSync(path, options = {}) {
path = getPathFromURL(path);
validatePath(path);
const ctx = { path };
const stats = binding.lstat(pathModule.toNamespacedPath(path),
undefined, ctx);
options.bigint, undefined, ctx);
handleErrorFromBinding(ctx);
return getStatsFromBinding(stats);
}

function statSync(path) {
function statSync(path, options = {}) {
path = getPathFromURL(path);
validatePath(path);
const ctx = { path };
const stats = binding.stat(pathModule.toNamespacedPath(path),
undefined, ctx);
options.bigint, undefined, ctx);
handleErrorFromBinding(ctx);
return getStatsFromBinding(stats);
}
Expand Down Expand Up @@ -1264,7 +1276,7 @@ function watchFile(filename, options, listener) {
if (stat === undefined) {
if (!watchers)
watchers = require('internal/fs/watchers');
stat = new watchers.StatWatcher();
stat = new watchers.StatWatcher(options.bigint);
stat.start(filename, options.persistent, options.interval);
statWatchers.set(filename, stat);
}
Expand Down Expand Up @@ -1379,7 +1391,7 @@ function realpathSync(p, options) {
// On windows, check that the root exists. On unix there is no need.
if (isWindows && !knownHard[base]) {
const ctx = { path: base };
binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx);
binding.lstat(pathModule.toNamespacedPath(base), false, undefined, ctx);
handleErrorFromBinding(ctx);
knownHard[base] = true;
}
Expand Down Expand Up @@ -1421,7 +1433,7 @@ function realpathSync(p, options) {

const baseLong = pathModule.toNamespacedPath(base);
const ctx = { path: base };
const stats = binding.lstat(baseLong, undefined, ctx);
const stats = binding.lstat(baseLong, false, undefined, ctx);
handleErrorFromBinding(ctx);

if (!isFileType(stats, S_IFLNK)) {
Expand All @@ -1444,7 +1456,7 @@ function realpathSync(p, options) {
}
if (linkTarget === null) {
const ctx = { path: base };
binding.stat(baseLong, undefined, ctx);
binding.stat(baseLong, false, undefined, ctx);
handleErrorFromBinding(ctx);
linkTarget = binding.readlink(baseLong, undefined, undefined, ctx);
handleErrorFromBinding(ctx);
Expand All @@ -1465,7 +1477,7 @@ function realpathSync(p, options) {
// On windows, check that the root exists. On unix there is no need.
if (isWindows && !knownHard[base]) {
const ctx = { path: base };
binding.lstat(pathModule.toNamespacedPath(base), undefined, ctx);
binding.lstat(pathModule.toNamespacedPath(base), false, undefined, ctx);
handleErrorFromBinding(ctx);
knownHard[base] = true;
}
Expand Down
19 changes: 9 additions & 10 deletions lib/internal/fs/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ class FileHandle {
return readFile(this, options);
}

stat() {
return fstat(this);
stat(options) {
return fstat(this, options);
}

truncate(len = 0) {
Expand All @@ -107,7 +107,6 @@ class FileHandle {
}
}


function validateFileHandle(handle) {
if (!(handle instanceof FileHandle))
throw new ERR_INVALID_ARG_TYPE('filehandle', 'FileHandle', handle);
Expand All @@ -128,7 +127,7 @@ async function writeFileHandle(filehandle, data, options) {
}

async function readFileHandle(filehandle, options) {
const statFields = await binding.fstat(filehandle.fd, kUsePromises);
const statFields = await binding.fstat(filehandle.fd, false, kUsePromises);

let size;
if ((statFields[1/* mode */] & S_IFMT) === S_IFREG) {
Expand Down Expand Up @@ -319,25 +318,25 @@ async function symlink(target, path, type_) {
kUsePromises);
}

async function fstat(handle) {
async function fstat(handle, options = { bigint: false }) {
validateFileHandle(handle);
const result = await binding.fstat(handle.fd, kUsePromises);
const result = await binding.fstat(handle.fd, options.bigint, kUsePromises);
return getStatsFromBinding(result);
}

async function lstat(path) {
async function lstat(path, options = { bigint: false }) {
path = getPathFromURL(path);
validatePath(path);
const result = await binding.lstat(pathModule.toNamespacedPath(path),
kUsePromises);
options.bigint, kUsePromises);
return getStatsFromBinding(result);
}

async function stat(path) {
async function stat(path, options = { bigint: false }) {
path = getPathFromURL(path);
validatePath(path);
const result = await binding.stat(pathModule.toNamespacedPath(path),
kUsePromises);
options.bigint, kUsePromises);
return getStatsFromBinding(result);
}

Expand Down
8 changes: 6 additions & 2 deletions lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function preprocessSymlinkDestination(path, type, linkPath) {
}

function dateFromNumeric(num) {
return new Date(num + 0.5);
return new Date(Number(num) + 0.5);
}

// Constructor for file stats.
Expand Down Expand Up @@ -155,7 +155,11 @@ function Stats(
}

Stats.prototype._checkModeProperty = function(property) {
return ((this.mode & S_IFMT) === property);
if (typeof this.mode === 'bigint') { // eslint-disable-line valid-typeof
// eslint-disable-next-line no-undef
return (this.mode & BigInt(S_IFMT)) === BigInt(property);
}
return (this.mode & S_IFMT) === property;
};

Stats.prototype.isDirectory = function() {
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/fs/watchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ function emitStop(self) {
self.emit('stop');
}

function StatWatcher() {
function StatWatcher(bigint) {
EventEmitter.call(this);

this._handle = new _StatWatcher();
this._handle = new _StatWatcher(bigint);

// uv_fs_poll is a little more powerful than ev_stat but we curb it for
// the sake of backwards compatibility
Expand Down
5 changes: 5 additions & 0 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ Environment::fs_stats_field_array() {
return &fs_stats_field_array_;
}

inline AliasedBuffer<uint64_t, v8::BigUint64Array>*
Environment::fs_stats_field_bigint_array() {
return &fs_stats_field_bigint_array_;
}

inline std::vector<std::unique_ptr<fs::FileHandleReadWrap>>&
Environment::file_handle_read_wrap_freelist() {
return file_handle_read_wrap_freelist_;
Expand Down
1 change: 1 addition & 0 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Environment::Environment(IsolateData* isolate_data,
#endif
http_parser_buffer_(nullptr),
fs_stats_field_array_(isolate_, kFsStatsFieldsLength * 2),
fs_stats_field_bigint_array_(isolate_, kFsStatsFieldsLength * 2),
context_(context->GetIsolate(), context) {
// We'll be creating new objects so make sure we've entered the context.
v8::HandleScope handle_scope(isolate());
Expand Down
3 changes: 3 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,8 @@ class Environment {
void set_debug_categories(const std::string& cats, bool enabled);

inline AliasedBuffer<double, v8::Float64Array>* fs_stats_field_array();
inline AliasedBuffer<uint64_t, v8::BigUint64Array>*
fs_stats_field_bigint_array();

// stat fields contains twice the number of entries because `fs.StatWatcher`
// needs room to store data for *two* `fs.Stats` instances.
Expand Down Expand Up @@ -869,6 +871,7 @@ class Environment {
bool debug_enabled_[static_cast<int>(DebugCategory::CATEGORY_COUNT)] = {0};

AliasedBuffer<double, v8::Float64Array> fs_stats_field_array_;
AliasedBuffer<uint64_t, v8::BigUint64Array> fs_stats_field_bigint_array_;

std::vector<std::unique_ptr<fs::FileHandleReadWrap>>
file_handle_read_wrap_freelist_;
Expand Down
Loading