From 0e36c55dbe1157a5d8837e2eb3ad5d783f708f9b Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Tue, 28 Nov 2023 20:18:16 -0500 Subject: [PATCH] fs: make stats date fields lazy --- lib/internal/fs/utils.js | 68 ++++++++++++++++++++++++++++++----- test/parallel/test-fs-stat.js | 6 ---- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index fa2851a244b5ee..e3e1c25f95ea5a 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -12,6 +12,8 @@ const { NumberIsFinite, MathMin, MathRound, + ObjectDefineProperties, + ObjectDefineProperty, ObjectIs, ObjectSetPrototypeOf, ReflectApply, @@ -449,6 +451,62 @@ function dateFromMs(ms) { return new Date(MathRound(Number(ms))); } +const lazyDateFields = { + __proto__: null, + atime: { + __proto__: null, + enumerable: true, + configurable: true, + get() { + const value = dateFromMs(this.atimeMs); + ObjectDefineProperty(this, 'atime', { __proto__: null, value }); + return this.atime; + }, + set(value) { + this.atime = value; + }, + }, + mtime: { + __proto__: null, + enumerable: true, + configurable: true, + get() { + const value = dateFromMs(this.mtimeMs); + ObjectDefineProperty(this, 'mtime', { __proto__: null, value }); + return this.mtime; + }, + set(value) { + this.mtime = value; + }, + }, + ctime: { + __proto__: null, + enumerable: true, + configurable: true, + get() { + const value = dateFromMs(this.ctimeMs); + ObjectDefineProperty(this, 'ctime', { __proto__: null, value }); + return this.ctime; + }, + set(value) { + this.ctime = value; + }, + }, + birthtime: { + __proto__: null, + enumerable: true, + configurable: true, + get() { + const value = dateFromMs(this.birthtimeMs); + ObjectDefineProperty(this, 'birthtime', { __proto__: null, value }); + return this.birthtime; + }, + set(value) { + this.birthtime = value; + }, + }, +}; + function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, ino, size, blocks, atimeNs, mtimeNs, ctimeNs, birthtimeNs) { @@ -463,14 +521,11 @@ function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, 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); } ObjectSetPrototypeOf(BigIntStats.prototype, StatsBase.prototype); ObjectSetPrototypeOf(BigIntStats, StatsBase); +ObjectDefineProperties(BigIntStats.prototype, lazyDateFields); BigIntStats.prototype._checkModeProperty = function(property) { if (isWindows && (property === S_IFIFO || property === S_IFBLK || @@ -489,14 +544,11 @@ function Stats(dev, mode, nlink, uid, gid, rdev, blksize, 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); } ObjectSetPrototypeOf(Stats.prototype, StatsBase.prototype); ObjectSetPrototypeOf(Stats, StatsBase); +ObjectDefineProperties(Stats.prototype, lazyDateFields); Stats.prototype._checkModeProperty = function(property) { if (isWindows && (property === S_IFIFO || property === S_IFBLK || diff --git a/test/parallel/test-fs-stat.js b/test/parallel/test-fs-stat.js index 8eca34c684035f..2b98698df65d36 100644 --- a/test/parallel/test-fs-stat.js +++ b/test/parallel/test-fs-stat.js @@ -80,8 +80,6 @@ fs.stat(__filename, common.mustSucceed((s) => { assert.strictEqual(s.isFIFO(), false); assert.strictEqual(s.isSymbolicLink(), false); - const jsonString = JSON.stringify(s); - const parsed = JSON.parse(jsonString); [ 'dev', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'blksize', 'ino', 'size', 'blocks', @@ -91,19 +89,15 @@ fs.stat(__filename, common.mustSucceed((s) => { assert.ok(k in s, `${k} should be in Stats`); assert.notStrictEqual(s[k], undefined, `${k} should not be undefined`); assert.notStrictEqual(s[k], null, `${k} should not be null`); - assert.notStrictEqual(parsed[k], undefined, `${k} should not be undefined`); - assert.notStrictEqual(parsed[k], null, `${k} should not be null`); }); [ 'dev', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'blksize', 'ino', 'size', 'blocks', 'atimeMs', 'mtimeMs', 'ctimeMs', 'birthtimeMs', ].forEach((k) => { assert.strictEqual(typeof s[k], 'number', `${k} should be a number`); - assert.strictEqual(typeof parsed[k], 'number', `${k} should be a number`); }); ['atime', 'mtime', 'ctime', 'birthtime'].forEach((k) => { assert.ok(s[k] instanceof Date, `${k} should be a Date`); - assert.strictEqual(typeof parsed[k], 'string', `${k} should be a string`); }); }));