Skip to content

Commit

Permalink
fs: convert stats to class and load dates lazily
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Nov 26, 2023
1 parent 7981e2e commit a2a7478
Showing 1 changed file with 147 additions and 74 deletions.
221 changes: 147 additions & 74 deletions lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ const {
DateNow,
DatePrototypeGetTime,
ErrorCaptureStackTrace,
FunctionPrototypeCall,
Number,
NumberIsFinite,
MathMin,
MathRound,
ObjectDefineProperties,
ObjectIs,
ObjectSetPrototypeOf,
ReflectApply,
ReflectOwnKeys,
RegExpPrototypeSymbolReplace,
StringPrototypeEndsWith,
Expand Down Expand Up @@ -382,47 +380,49 @@ function preprocessSymlinkDestination(path, type, linkPath) {
}

// Constructor for file stats.
function StatsBase(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks) {
this.dev = dev;
this.mode = mode;
this.nlink = nlink;
this.uid = uid;
this.gid = gid;
this.rdev = rdev;
this.blksize = blksize;
this.ino = ino;
this.size = size;
this.blocks = blocks;
}
class StatsBase {
constructor(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks) {
this.dev = dev;
this.mode = mode;
this.nlink = nlink;
this.uid = uid;
this.gid = gid;
this.rdev = rdev;
this.blksize = blksize;
this.ino = ino;
this.size = size;
this.blocks = blocks;
}

StatsBase.prototype.isDirectory = function() {
return this._checkModeProperty(S_IFDIR);
};
isDirectory() {
return this._checkModeProperty(S_IFDIR);
}

StatsBase.prototype.isFile = function() {
return this._checkModeProperty(S_IFREG);
};
isFile() {
return this._checkModeProperty(S_IFREG);
}

StatsBase.prototype.isBlockDevice = function() {
return this._checkModeProperty(S_IFBLK);
};
isBlockDevice() {
return this._checkModeProperty(S_IFBLK);
}

StatsBase.prototype.isCharacterDevice = function() {
return this._checkModeProperty(S_IFCHR);
};
isCharacterDevice() {
return this._checkModeProperty(S_IFCHR);
}

StatsBase.prototype.isSymbolicLink = function() {
return this._checkModeProperty(S_IFLNK);
};
isSymbolicLink() {
return this._checkModeProperty(S_IFLNK);
}

StatsBase.prototype.isFIFO = function() {
return this._checkModeProperty(S_IFIFO);
};
isFIFO() {
return this._checkModeProperty(S_IFIFO);
}

StatsBase.prototype.isSocket = function() {
return this._checkModeProperty(S_IFSOCK);
};
isSocket() {
return this._checkModeProperty(S_IFSOCK);
}
}

const kNsPerMsBigInt = 10n ** 6n;
const kNsPerSecBigInt = 10n ** 9n;
Expand All @@ -448,29 +448,65 @@ function dateFromMs(ms) {
return new Date(MathRound(Number(ms)));
}

function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks,
atimeNs, mtimeNs, ctimeNs, birthtimeNs) {
ReflectApply(StatsBase, this, [dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks]);

this.atimeMs = atimeNs / kNsPerMsBigInt;
this.mtimeMs = mtimeNs / kNsPerMsBigInt;
this.ctimeMs = ctimeNs / kNsPerMsBigInt;
this.birthtimeMs = birthtimeNs / kNsPerMsBigInt;
this.atimeNs = atimeNs;
this.mtimeNs = mtimeNs;
this.ctimeNs = ctimeNs;
this.birthtimeNs = birthtimeNs;
this.atime = dateFromMs(this.atimeMs);
this.mtime = dateFromMs(this.mtimeMs);
this.ctime = dateFromMs(this.ctimeMs);
this.birthtime = dateFromMs(this.birthtimeMs);
class BigIntStats extends StatsBase {
#atime;
#mtime;
#ctime;
#birthtime;

constructor(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks,
atimeNs, mtimeNs, ctimeNs, birthtimeNs) {
super(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks);

this.atimeMs = atimeNs / kNsPerMsBigInt;
this.mtimeMs = mtimeNs / kNsPerMsBigInt;
this.ctimeMs = ctimeNs / kNsPerMsBigInt;
this.birthtimeMs = birthtimeNs / kNsPerMsBigInt;
this.atimeNs = atimeNs;
this.mtimeNs = mtimeNs;
this.ctimeNs = ctimeNs;
this.birthtimeNs = birthtimeNs;

ObjectDefineProperties(this, {
__proto__: null,
atime: {
__proto__: null,
enumerable: true,
get() {
this.#atime ??= dateFromMs(this.atimeMs);
return this.#atime;
},
},
mtime: {
__proto__: null,
enumerable: true,
get() {
this.#mtime ??= dateFromMs(this.mtimeMs);
return this.#mtime;
},
},
ctime: {
__proto__: null,
enumerable: true,
get() {
this.#ctime ??= dateFromMs(this.ctimeMs);
return this.#ctime;
},
},
birthtime: {
__proto__: null,
enumerable: true,
get() {
this.#birthtime ??= dateFromMs(this.birthtimeMs);
return this.#birthtime;
},
},
});
}
}

ObjectSetPrototypeOf(BigIntStats.prototype, StatsBase.prototype);
ObjectSetPrototypeOf(BigIntStats, StatsBase);

BigIntStats.prototype._checkModeProperty = function(property) {
if (isWindows && (property === S_IFIFO || property === S_IFBLK ||
property === S_IFSOCK)) {
Expand All @@ -479,24 +515,61 @@ BigIntStats.prototype._checkModeProperty = function(property) {
return (this.mode & BigInt(S_IFMT)) === BigInt(property);
};

function Stats(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks,
atimeMs, mtimeMs, ctimeMs, birthtimeMs) {
FunctionPrototypeCall(StatsBase, this, dev, mode, nlink, uid, gid, rdev,
blksize, ino, size, blocks);
this.atimeMs = atimeMs;
this.mtimeMs = mtimeMs;
this.ctimeMs = ctimeMs;
this.birthtimeMs = birthtimeMs;
this.atime = dateFromMs(atimeMs);
this.mtime = dateFromMs(mtimeMs);
this.ctime = dateFromMs(ctimeMs);
this.birthtime = dateFromMs(birthtimeMs);
class Stats extends StatsBase {
#atime;
#mtime;
#ctime;
#birthtime;

constructor(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks,
atimeMs, mtimeMs, ctimeMs, birthtimeMs) {
super(dev, mode, nlink, uid, gid, rdev,
blksize, ino, size, blocks);

this.atimeMs = atimeMs;
this.mtimeMs = mtimeMs;
this.ctimeMs = ctimeMs;
this.birthtimeMs = birthtimeMs;

ObjectDefineProperties(this, {
__proto__: null,
atime: {
__proto__: null,
enumerable: true,
get() {
this.#atime ??= dateFromMs(this.atimeMs);
return this.#atime;
},
},
mtime: {
__proto__: null,
enumerable: true,
get() {
this.#mtime ??= dateFromMs(this.mtimeMs);
return this.#mtime;
},
},
ctime: {
__proto__: null,
enumerable: true,
get() {
this.#ctime ??= dateFromMs(this.ctimeMs);
return this.#ctime;
},
},
birthtime: {
__proto__: null,
enumerable: true,
get() {
this.#birthtime ??= dateFromMs(this.birthtimeMs);
return this.#birthtime;
},
},
});
}
}

ObjectSetPrototypeOf(Stats.prototype, StatsBase.prototype);
ObjectSetPrototypeOf(Stats, StatsBase);

// HACK: Workaround for https://github.com/standard-things/esm/issues/821.
// TODO(ronag): Remove this as soon as `esm` publishes a fixed version.
Stats.prototype.isFile = StatsBase.prototype.isFile;
Expand Down

0 comments on commit a2a7478

Please sign in to comment.