diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2018-06-19 02:58:49 +0800 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2019-06-14 03:24:41 +0800 |
commit | b245257b70750bdc52a8c315de4b10965dacfed6 (patch) | |
tree | 004c92ceffe5f568ec5d06b592aaa38b157c80fe /lib/internal/fs/utils.js | |
parent | 4b1bcae681e209984604341f2acfe722345b1b23 (diff) | |
download | android-node-v8-b245257b70750bdc52a8c315de4b10965dacfed6.tar.gz android-node-v8-b245257b70750bdc52a8c315de4b10965dacfed6.tar.bz2 android-node-v8-b245257b70750bdc52a8c315de4b10965dacfed6.zip |
fs: add *timeNs properties to BigInt Stats objects
- Extend the aliased buffer for stats objects to contain
the entire time spec (seconds and nanoseconds) for the time
values instead of calculating the milliseconds in C++ and
lose precision there.
- Calculate the nanosecond-precision time values in JS and expose
them in BigInt Stats objects as `*timeNs`. The
millisecond-precision values are now calculated from the
nanosecond-precision values.
PR-URL: https://github.com/nodejs/node/pull/21387
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Diffstat (limited to 'lib/internal/fs/utils.js')
-rw-r--r-- | lib/internal/fs/utils.js | 163 |
1 files changed, 108 insertions, 55 deletions
diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 14abad81ec..6cd6f7aceb 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -1,6 +1,6 @@ 'use strict'; -const { Reflect } = primordials; +const { Object, Reflect } = primordials; const { Buffer, kMaxLength } = require('buffer'); const { @@ -16,7 +16,8 @@ const { } = require('internal/errors'); const { isUint8Array, - isDate + isDate, + isBigUint64Array } = require('internal/util/types'); const { once } = require('internal/util'); const { toPathIfFileURL } = require('internal/url'); @@ -230,27 +231,9 @@ function preprocessSymlinkDestination(path, type, linkPath) { } } -function dateFromNumeric(num) { - return new Date(Number(num) + 0.5); -} - // Constructor for file stats. -function Stats( - dev, - mode, - nlink, - uid, - gid, - rdev, - blksize, - ino, - size, - blocks, - atim_msec, - mtim_msec, - ctim_msec, - birthtim_msec -) { +function StatsBase(dev, mode, nlink, uid, gid, rdev, blksize, + ino, size, blocks) { this.dev = dev; this.mode = mode; this.nlink = nlink; @@ -261,63 +244,132 @@ function Stats( this.ino = ino; this.size = size; this.blocks = blocks; - this.atimeMs = atim_msec; - this.mtimeMs = mtim_msec; - this.ctimeMs = ctim_msec; - this.birthtimeMs = birthtim_msec; - this.atime = dateFromNumeric(atim_msec); - this.mtime = dateFromNumeric(mtim_msec); - this.ctime = dateFromNumeric(ctim_msec); - this.birthtime = dateFromNumeric(birthtim_msec); } -Stats.prototype._checkModeProperty = function(property) { - if (isWindows && (property === S_IFIFO || property === S_IFBLK || - property === S_IFSOCK)) { - return false; // Some types are not available on Windows - } - if (typeof this.mode === 'bigint') { // eslint-disable-line valid-typeof - return (this.mode & BigInt(S_IFMT)) === BigInt(property); - } - return (this.mode & S_IFMT) === property; -}; - -Stats.prototype.isDirectory = function() { +StatsBase.prototype.isDirectory = function() { return this._checkModeProperty(S_IFDIR); }; -Stats.prototype.isFile = function() { +StatsBase.prototype.isFile = function() { return this._checkModeProperty(S_IFREG); }; -Stats.prototype.isBlockDevice = function() { +StatsBase.prototype.isBlockDevice = function() { return this._checkModeProperty(S_IFBLK); }; -Stats.prototype.isCharacterDevice = function() { +StatsBase.prototype.isCharacterDevice = function() { return this._checkModeProperty(S_IFCHR); }; -Stats.prototype.isSymbolicLink = function() { +StatsBase.prototype.isSymbolicLink = function() { return this._checkModeProperty(S_IFLNK); }; -Stats.prototype.isFIFO = function() { +StatsBase.prototype.isFIFO = function() { return this._checkModeProperty(S_IFIFO); }; -Stats.prototype.isSocket = function() { +StatsBase.prototype.isSocket = function() { return this._checkModeProperty(S_IFSOCK); }; +const kNsPerMsBigInt = 10n ** 6n; +const kNsPerSecBigInt = 10n ** 9n; +const kMsPerSec = 10 ** 3; +const kNsPerMs = 10 ** 6; +function msFromTimeSpec(sec, nsec) { + return sec * kMsPerSec + nsec / kNsPerMs; +} + +function nsFromTimeSpecBigInt(sec, nsec) { + return sec * kNsPerSecBigInt + nsec; +} + +function dateFromMs(ms) { + return new Date(Number(ms) + 0.5); +} + +function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, + ino, size, blocks, + atimeNs, mtimeNs, ctimeNs, birthtimeNs) { + StatsBase.call(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); +} + +Object.setPrototypeOf(BigIntStats.prototype, StatsBase.prototype); +Object.setPrototypeOf(BigIntStats, StatsBase); + +BigIntStats.prototype._checkModeProperty = function(property) { + if (isWindows && (property === S_IFIFO || property === S_IFBLK || + property === S_IFSOCK)) { + return false; // Some types are not available on Windows + } + return (this.mode & BigInt(S_IFMT)) === BigInt(property); +}; + +function Stats(dev, mode, nlink, uid, gid, rdev, blksize, + ino, size, blocks, + atimeMs, mtimeMs, ctimeMs, birthtimeMs) { + StatsBase.call(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); +} + +Object.setPrototypeOf(Stats.prototype, StatsBase.prototype); +Object.setPrototypeOf(Stats, StatsBase); + +Stats.prototype._checkModeProperty = function(property) { + if (isWindows && (property === S_IFIFO || property === S_IFBLK || + property === S_IFSOCK)) { + return false; // Some types are not available on Windows + } + return (this.mode & S_IFMT) === property; +}; + function getStatsFromBinding(stats, offset = 0) { - return new Stats(stats[0 + offset], stats[1 + offset], stats[2 + offset], - stats[3 + offset], stats[4 + offset], stats[5 + offset], - stats[6 + offset], // blksize - stats[7 + offset], stats[8 + offset], - stats[9 + offset], // blocks - stats[10 + offset], stats[11 + offset], - stats[12 + offset], stats[13 + offset]); + if (isBigUint64Array(stats)) { + return new BigIntStats( + stats[0 + offset], stats[1 + offset], stats[2 + offset], + stats[3 + offset], stats[4 + offset], stats[5 + offset], + stats[6 + offset], stats[7 + offset], stats[8 + offset], + stats[9 + offset], + nsFromTimeSpecBigInt(stats[10 + offset], stats[11 + offset]), + nsFromTimeSpecBigInt(stats[12 + offset], stats[13 + offset]), + nsFromTimeSpecBigInt(stats[14 + offset], stats[15 + offset]), + nsFromTimeSpecBigInt(stats[16 + offset], stats[17 + offset]) + ); + } + return new Stats( + stats[0 + offset], stats[1 + offset], stats[2 + offset], + stats[3 + offset], stats[4 + offset], stats[5 + offset], + stats[6 + offset], stats[7 + offset], stats[8 + offset], + stats[9 + offset], + msFromTimeSpec(stats[10 + offset], stats[11 + offset]), + msFromTimeSpec(stats[12 + offset], stats[13 + offset]), + msFromTimeSpec(stats[14 + offset], stats[15 + offset]), + msFromTimeSpec(stats[16 + offset], stats[17 + offset]) + ); } function stringToFlags(flags) { @@ -453,6 +505,7 @@ function warnOnNonPortableTemplate(template) { module.exports = { assertEncoding, + BigIntStats, // for testing copyObject, Dirent, getDirents, |