Skip to content

Commit bc636a7

Browse files
LiviaMedeirosjuanarbol
authored andcommitted
fs: make Date properties on Stats enumerable
Signed-off-by: LiviaMedeiros <livia@cirno.name> PR-URL: #63328 Reviewed-By: René <contact.9a5d6388@renegade334.me.uk> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent 8455b62 commit bc636a7

3 files changed

Lines changed: 22 additions & 10 deletions

File tree

lib/internal/fs/utils.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const {
1313
Number,
1414
NumberIsFinite,
1515
ObjectDefineProperties,
16-
ObjectDefineProperty,
1716
ObjectIs,
1817
ObjectSetPrototypeOf,
1918
ReflectApply,
@@ -50,6 +49,7 @@ const {
5049
once,
5150
deprecate,
5251
isWindows,
52+
setOwnProperty,
5353
} = require('internal/util');
5454
const { toPathIfFileURL } = require('internal/url');
5555
const {
@@ -452,43 +452,43 @@ const lazyDateFields = {
452452
enumerable: true,
453453
configurable: true,
454454
get() {
455-
return this.atime = dateFromMs(this.atimeMs);
455+
return setOwnProperty(this, 'atime', dateFromMs(this.atimeMs));
456456
},
457457
set(value) {
458-
ObjectDefineProperty(this, 'atime', { __proto__: null, value, writable: true });
458+
setOwnProperty(this, 'atime', value);
459459
},
460460
},
461461
mtime: {
462462
__proto__: null,
463463
enumerable: true,
464464
configurable: true,
465465
get() {
466-
return this.mtime = dateFromMs(this.mtimeMs);
466+
return setOwnProperty(this, 'mtime', dateFromMs(this.mtimeMs));
467467
},
468468
set(value) {
469-
ObjectDefineProperty(this, 'mtime', { __proto__: null, value, writable: true });
469+
setOwnProperty(this, 'mtime', value);
470470
},
471471
},
472472
ctime: {
473473
__proto__: null,
474474
enumerable: true,
475475
configurable: true,
476476
get() {
477-
return this.ctime = dateFromMs(this.ctimeMs);
477+
return setOwnProperty(this, 'ctime', dateFromMs(this.ctimeMs));
478478
},
479479
set(value) {
480-
ObjectDefineProperty(this, 'ctime', { __proto__: null, value, writable: true });
480+
setOwnProperty(this, 'ctime', value);
481481
},
482482
},
483483
birthtime: {
484484
__proto__: null,
485485
enumerable: true,
486486
configurable: true,
487487
get() {
488-
return this.birthtime = dateFromMs(this.birthtimeMs);
488+
return setOwnProperty(this, 'birthtime', dateFromMs(this.birthtimeMs));
489489
},
490490
set(value) {
491-
ObjectDefineProperty(this, 'birthtime', { __proto__: null, value, writable: true });
491+
setOwnProperty(this, 'birthtime', value);
492492
},
493493
},
494494
};

lib/internal/util.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,13 +730,14 @@ function filterOwnProperties(source, keys) {
730730
* @returns {any}
731731
*/
732732
function setOwnProperty(obj, key, value) {
733-
return ObjectDefineProperty(obj, key, {
733+
ObjectDefineProperty(obj, key, {
734734
__proto__: null,
735735
configurable: true,
736736
enumerable: true,
737737
value,
738738
writable: true,
739739
});
740+
return value;
740741
}
741742

742743
let internalGlobal;

test/parallel/test-fs-stat-date.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ function closeEnough(actual, expected, margin) {
4242
`expected ${expected} ± ${margin}, got ${actual}`);
4343
}
4444

45+
// Ensure that accessed atime and mtime are enumerable
46+
function validateEnumerability(stats) {
47+
const keys = Object.keys(stats);
48+
assert.ok(keys.includes('atime'));
49+
assert.ok(keys.includes('mtime'));
50+
}
51+
4552
async function runTest(atime, mtime, margin = 0) {
4653
margin += Number.EPSILON;
4754
try {
@@ -56,24 +63,28 @@ async function runTest(atime, mtime, margin = 0) {
5663
closeEnough(stats.mtimeMs, mtime, margin);
5764
closeEnough(stats.atime.getTime(), new Date(atime).getTime(), margin);
5865
closeEnough(stats.mtime.getTime(), new Date(mtime).getTime(), margin);
66+
validateEnumerability(stats);
5967

6068
const statsBigint = await fsPromises.stat(filepath, { bigint: true });
6169
closeEnough(statsBigint.atimeMs, BigInt(atime), margin);
6270
closeEnough(statsBigint.mtimeMs, BigInt(mtime), margin);
6371
closeEnough(statsBigint.atime.getTime(), new Date(atime).getTime(), margin);
6472
closeEnough(statsBigint.mtime.getTime(), new Date(mtime).getTime(), margin);
73+
validateEnumerability(statsBigint);
6574

6675
const statsSync = fs.statSync(filepath);
6776
closeEnough(statsSync.atimeMs, atime, margin);
6877
closeEnough(statsSync.mtimeMs, mtime, margin);
6978
closeEnough(statsSync.atime.getTime(), new Date(atime).getTime(), margin);
7079
closeEnough(statsSync.mtime.getTime(), new Date(mtime).getTime(), margin);
80+
validateEnumerability(statsSync);
7181

7282
const statsSyncBigint = fs.statSync(filepath, { bigint: true });
7383
closeEnough(statsSyncBigint.atimeMs, BigInt(atime), margin);
7484
closeEnough(statsSyncBigint.mtimeMs, BigInt(mtime), margin);
7585
closeEnough(statsSyncBigint.atime.getTime(), new Date(atime).getTime(), margin);
7686
closeEnough(statsSyncBigint.mtime.getTime(), new Date(mtime).getTime(), margin);
87+
validateEnumerability(statsSyncBigint);
7788
}
7889

7990
// Too high/low numbers produce too different results on different platforms

0 commit comments

Comments
 (0)