summaryrefslogtreecommitdiff
path: root/lib/internal/fs/utils.js
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2018-06-19 02:58:49 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2019-06-14 03:24:41 +0800
commitb245257b70750bdc52a8c315de4b10965dacfed6 (patch)
tree004c92ceffe5f568ec5d06b592aaa38b157c80fe /lib/internal/fs/utils.js
parent4b1bcae681e209984604341f2acfe722345b1b23 (diff)
downloadandroid-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.js163
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,