From a2a747882b2b6f64296c011420aa50cf965674b3 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Sat, 25 Nov 2023 14:47:04 -0500 Subject: [PATCH] fs: convert stats to class and load dates lazily --- lib/internal/fs/utils.js | 221 ++++++++++++++++++++++++++------------- 1 file changed, 147 insertions(+), 74 deletions(-) diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 9f5ad9bf5f6c0e..d5bb21c44d51c2 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -7,14 +7,12 @@ const { DateNow, DatePrototypeGetTime, ErrorCaptureStackTrace, - FunctionPrototypeCall, Number, NumberIsFinite, MathMin, MathRound, + ObjectDefineProperties, ObjectIs, - ObjectSetPrototypeOf, - ReflectApply, ReflectOwnKeys, RegExpPrototypeSymbolReplace, StringPrototypeEndsWith, @@ -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; @@ -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)) { @@ -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;