Skip to content

Commit abbdc3e

Browse files
authored
fs: make stats date fields lazy
PR-URL: #50908 Reviewed-By: Raz Luvaton <rluvaton@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 7afaf46 commit abbdc3e

File tree

2 files changed

+60
-14
lines changed

2 files changed

+60
-14
lines changed

lib/internal/fs/utils.js

+60-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const {
1212
NumberIsFinite,
1313
MathMin,
1414
MathRound,
15+
ObjectDefineProperties,
16+
ObjectDefineProperty,
1517
ObjectIs,
1618
ObjectSetPrototypeOf,
1719
ReflectApply,
@@ -449,6 +451,62 @@ function dateFromMs(ms) {
449451
return new Date(MathRound(Number(ms)));
450452
}
451453

454+
const lazyDateFields = {
455+
__proto__: null,
456+
atime: {
457+
__proto__: null,
458+
enumerable: true,
459+
configurable: true,
460+
get() {
461+
const value = dateFromMs(this.atimeMs);
462+
ObjectDefineProperty(this, 'atime', { __proto__: null, value });
463+
return this.atime;
464+
},
465+
set(value) {
466+
this.atime = value;
467+
},
468+
},
469+
mtime: {
470+
__proto__: null,
471+
enumerable: true,
472+
configurable: true,
473+
get() {
474+
const value = dateFromMs(this.mtimeMs);
475+
ObjectDefineProperty(this, 'mtime', { __proto__: null, value });
476+
return this.mtime;
477+
},
478+
set(value) {
479+
this.mtime = value;
480+
},
481+
},
482+
ctime: {
483+
__proto__: null,
484+
enumerable: true,
485+
configurable: true,
486+
get() {
487+
const value = dateFromMs(this.ctimeMs);
488+
ObjectDefineProperty(this, 'ctime', { __proto__: null, value });
489+
return this.ctime;
490+
},
491+
set(value) {
492+
this.ctime = value;
493+
},
494+
},
495+
birthtime: {
496+
__proto__: null,
497+
enumerable: true,
498+
configurable: true,
499+
get() {
500+
const value = dateFromMs(this.birthtimeMs);
501+
ObjectDefineProperty(this, 'birthtime', { __proto__: null, value });
502+
return this.birthtime;
503+
},
504+
set(value) {
505+
this.birthtime = value;
506+
},
507+
},
508+
};
509+
452510
function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize,
453511
ino, size, blocks,
454512
atimeNs, mtimeNs, ctimeNs, birthtimeNs) {
@@ -463,14 +521,11 @@ function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize,
463521
this.mtimeNs = mtimeNs;
464522
this.ctimeNs = ctimeNs;
465523
this.birthtimeNs = birthtimeNs;
466-
this.atime = dateFromMs(this.atimeMs);
467-
this.mtime = dateFromMs(this.mtimeMs);
468-
this.ctime = dateFromMs(this.ctimeMs);
469-
this.birthtime = dateFromMs(this.birthtimeMs);
470524
}
471525

472526
ObjectSetPrototypeOf(BigIntStats.prototype, StatsBase.prototype);
473527
ObjectSetPrototypeOf(BigIntStats, StatsBase);
528+
ObjectDefineProperties(BigIntStats.prototype, lazyDateFields);
474529

475530
BigIntStats.prototype._checkModeProperty = function(property) {
476531
if (isWindows && (property === S_IFIFO || property === S_IFBLK ||
@@ -489,14 +544,11 @@ function Stats(dev, mode, nlink, uid, gid, rdev, blksize,
489544
this.mtimeMs = mtimeMs;
490545
this.ctimeMs = ctimeMs;
491546
this.birthtimeMs = birthtimeMs;
492-
this.atime = dateFromMs(atimeMs);
493-
this.mtime = dateFromMs(mtimeMs);
494-
this.ctime = dateFromMs(ctimeMs);
495-
this.birthtime = dateFromMs(birthtimeMs);
496547
}
497548

498549
ObjectSetPrototypeOf(Stats.prototype, StatsBase.prototype);
499550
ObjectSetPrototypeOf(Stats, StatsBase);
551+
ObjectDefineProperties(Stats.prototype, lazyDateFields);
500552

501553
Stats.prototype._checkModeProperty = function(property) {
502554
if (isWindows && (property === S_IFIFO || property === S_IFBLK ||

test/parallel/test-fs-stat.js

-6
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ fs.stat(__filename, common.mustSucceed((s) => {
8080
assert.strictEqual(s.isFIFO(), false);
8181
assert.strictEqual(s.isSymbolicLink(), false);
8282

83-
const jsonString = JSON.stringify(s);
84-
const parsed = JSON.parse(jsonString);
8583
[
8684
'dev', 'mode', 'nlink', 'uid',
8785
'gid', 'rdev', 'blksize', 'ino', 'size', 'blocks',
@@ -91,19 +89,15 @@ fs.stat(__filename, common.mustSucceed((s) => {
9189
assert.ok(k in s, `${k} should be in Stats`);
9290
assert.notStrictEqual(s[k], undefined, `${k} should not be undefined`);
9391
assert.notStrictEqual(s[k], null, `${k} should not be null`);
94-
assert.notStrictEqual(parsed[k], undefined, `${k} should not be undefined`);
95-
assert.notStrictEqual(parsed[k], null, `${k} should not be null`);
9692
});
9793
[
9894
'dev', 'mode', 'nlink', 'uid', 'gid', 'rdev', 'blksize', 'ino', 'size',
9995
'blocks', 'atimeMs', 'mtimeMs', 'ctimeMs', 'birthtimeMs',
10096
].forEach((k) => {
10197
assert.strictEqual(typeof s[k], 'number', `${k} should be a number`);
102-
assert.strictEqual(typeof parsed[k], 'number', `${k} should be a number`);
10398
});
10499
['atime', 'mtime', 'ctime', 'birthtime'].forEach((k) => {
105100
assert.ok(s[k] instanceof Date, `${k} should be a Date`);
106-
assert.strictEqual(typeof parsed[k], 'string', `${k} should be a string`);
107101
});
108102
}));
109103

0 commit comments

Comments
 (0)