-
-
Notifications
You must be signed in to change notification settings - Fork 33.8k
fs: add Temporal.Instant support to Stats and BigIntStats
#60789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ const { | |||||
| DatePrototypeGetTime, | ||||||
| ErrorCaptureStackTrace, | ||||||
| FunctionPrototypeCall, | ||||||
| MathFloor, | ||||||
| MathMin, | ||||||
| MathRound, | ||||||
| Number, | ||||||
|
|
@@ -34,6 +35,7 @@ const { | |||||
| ERR_INCOMPATIBLE_OPTION_PAIR, | ||||||
| ERR_INVALID_ARG_TYPE, | ||||||
| ERR_INVALID_ARG_VALUE, | ||||||
| ERR_NO_TEMPORAL, | ||||||
| ERR_OUT_OF_RANGE, | ||||||
| }, | ||||||
| hideStackFrames, | ||||||
|
|
@@ -63,6 +65,10 @@ const { | |||||
| const pathModule = require('path'); | ||||||
| const kType = Symbol('type'); | ||||||
| const kStats = Symbol('stats'); | ||||||
| const kPartialAtimeNs = Symbol('partialAtimeNs'); | ||||||
| const kPartialMtimeNs = Symbol('partialMtimeNs'); | ||||||
| const kPartialCtimeNs = Symbol('partialCtimeNs'); | ||||||
| const kPartialBirthtimeNs = Symbol('kPartialBirthtimeNs'); | ||||||
| const assert = require('internal/assert'); | ||||||
|
|
||||||
| const { | ||||||
|
|
@@ -431,6 +437,22 @@ function nsFromTimeSpecBigInt(sec, nsec) { | |||||
| return sec * kNsPerSecBigInt + nsec; | ||||||
| } | ||||||
|
|
||||||
| function instantFromNs(nsec) { | ||||||
| if (Temporal === undefined) { | ||||||
| throw new ERR_NO_TEMPORAL(); | ||||||
| } | ||||||
| // TODO(LiviaMedeiros): TemporalInstant primordial | ||||||
| return new Temporal.Instant(nsec); | ||||||
| } | ||||||
|
|
||||||
| function instantFromTimeSpecMs(msec, nsec) { | ||||||
| if (Temporal === undefined) { | ||||||
| throw new ERR_NO_TEMPORAL(); | ||||||
| } | ||||||
| // TODO(LiviaMedeiros): TemporalInstant primordial | ||||||
| return new Temporal.Instant(BigInt(MathFloor(msec / kMsPerSec)) * kNsPerSecBigInt + BigInt(nsec)); | ||||||
| } | ||||||
|
|
||||||
| // The Date constructor performs Math.floor() on the absolute value | ||||||
| // of the timestamp: https://tc39.es/ecma262/#sec-timeclip | ||||||
| // Since there may be a precision loss when the timestamp is | ||||||
|
|
@@ -491,6 +513,102 @@ const lazyDateFields = { | |||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| const lazyTemporalFields = { | ||||||
| __proto__: null, | ||||||
| atimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.atimeInstant = instantFromTimeSpecMs(this.atimeMs, this[kPartialAtimeNs]); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'atimeInstant', { __proto__: null, value, writable: true }); | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICT this will make the property enumerable, even though the initial getter is not? I don't mind it, but this better be aligned with how
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should probably add an additional optional |
||||||
| }, | ||||||
| }, | ||||||
| mtimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.mtimeInstant = instantFromTimeSpecMs(this.mtimeMs, this[kPartialMtimeNs]); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'mtimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| ctimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.ctimeInstant = instantFromTimeSpecMs(this.ctimeMs, this[kPartialCtimeNs]);; | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'ctimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| birthtimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.birthtimeInstant = instantFromTimeSpecMs(this.birthtimeMs, this[kPartialBirthtimeNs]);; | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'birthtimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| const lazyTemporalBigIntFields = { | ||||||
| __proto__: null, | ||||||
| atimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.atimeInstant = instantFromNs(this.atimeNs); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'atimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| mtimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.mtimeInstant = instantFromNs(this.mtimeNs); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'mtimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| ctimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.ctimeInstant = instantFromNs(this.ctimeNs); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'ctimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| birthtimeInstant: { | ||||||
| __proto__: null, | ||||||
| enumerable: true, | ||||||
| configurable: true, | ||||||
| get() { | ||||||
| return this.birthtimeInstant = instantFromNs(this.birthtimeNs); | ||||||
| }, | ||||||
| set(value) { | ||||||
| ObjectDefineProperty(this, 'birthtimeInstant', { __proto__: null, value, writable: true }); | ||||||
| }, | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, | ||||||
| ino, size, blocks, | ||||||
| atimeNs, mtimeNs, ctimeNs, birthtimeNs) { | ||||||
|
|
@@ -510,6 +628,7 @@ function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, | |||||
| ObjectSetPrototypeOf(BigIntStats.prototype, StatsBase.prototype); | ||||||
| ObjectSetPrototypeOf(BigIntStats, StatsBase); | ||||||
| ObjectDefineProperties(BigIntStats.prototype, lazyDateFields); | ||||||
| ObjectDefineProperties(BigIntStats.prototype, lazyTemporalBigIntFields); | ||||||
|
|
||||||
| BigIntStats.prototype._checkModeProperty = function(property) { | ||||||
| if (isWindows && (property === S_IFIFO || property === S_IFBLK || | ||||||
|
|
@@ -521,18 +640,23 @@ BigIntStats.prototype._checkModeProperty = function(property) { | |||||
|
|
||||||
| function Stats(dev, mode, nlink, uid, gid, rdev, blksize, | ||||||
| ino, size, blocks, | ||||||
| atimeMs, mtimeMs, ctimeMs, birthtimeMs) { | ||||||
| atimeS, atimeNs, mtimeS, mtimeNs, ctimeS, ctimeNs, birthtimeS, birthtimeNs) { | ||||||
| FunctionPrototypeCall(StatsBase, this, dev, mode, nlink, uid, gid, rdev, | ||||||
| blksize, ino, size, blocks); | ||||||
| this.atimeMs = atimeMs; | ||||||
| this.mtimeMs = mtimeMs; | ||||||
| this.ctimeMs = ctimeMs; | ||||||
| this.birthtimeMs = birthtimeMs; | ||||||
| this.atimeMs = msFromTimeSpec(atimeS, atimeNs); | ||||||
| this.mtimeMs = msFromTimeSpec(mtimeS, mtimeNs); | ||||||
| this.ctimeMs = msFromTimeSpec(ctimeS, ctimeNs); | ||||||
| this.birthtimeMs = msFromTimeSpec(birthtimeS, birthtimeNs); | ||||||
| this[kPartialAtimeNs] = atimeNs; | ||||||
| this[kPartialMtimeNs] = mtimeNs; | ||||||
| this[kPartialCtimeNs] = ctimeNs; | ||||||
| this[kPartialBirthtimeNs] = birthtimeNs; | ||||||
| } | ||||||
|
|
||||||
| ObjectSetPrototypeOf(Stats.prototype, StatsBase.prototype); | ||||||
| ObjectSetPrototypeOf(Stats, StatsBase); | ||||||
| ObjectDefineProperties(Stats.prototype, lazyDateFields); | ||||||
| ObjectDefineProperties(Stats.prototype, lazyTemporalFields); | ||||||
|
|
||||||
| Stats.prototype._checkModeProperty = function(property) { | ||||||
| if (isWindows && (property === S_IFIFO || property === S_IFBLK || | ||||||
|
|
@@ -565,10 +689,10 @@ function getStatsFromBinding(stats, offset = 0) { | |||||
| 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]), | ||||||
| stats[10 + offset], stats[11 + offset], // atime | ||||||
| stats[12 + offset], stats[13 + offset], // mtime | ||||||
| stats[14 + offset], stats[15 + offset], // ctime | ||||||
| stats[16 + offset], stats[17 + offset], // birthtime | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're probably going to want to support building
nodewithoutTemporalsupport for a whileThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, especially with mandatory Rust requirements.
Added the error, the message text is subject to changes (if this may land before enabling Temporal by default, it should also suggest
--harmony-temporalflag)