Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2465,6 +2465,17 @@ OpenSSL crypto support.
An attempt was made to use features that require [ICU][], but Node.js was not
compiled with ICU support.

<a id="ERR_NO_TEMPORAL"></a>

### `ERR_NO_TEMPORAL`
Comment thread
LiviaMedeiros marked this conversation as resolved.

<!-- YAML
added: REPLACEME
-->

An attempt was made to use features that require [`Temporal`][], but Node.js was
compiled with `Temporal` support disabled.

<a id="ERR_NO_TYPESCRIPT"></a>

### `ERR_NO_TYPESCRIPT`
Expand Down Expand Up @@ -4472,6 +4483,7 @@ An error occurred trying to allocate memory. This should never happen.
[`QuicError`]: quic.md#class-quicerror
[`REPL`]: repl.md
[`ServerResponse`]: http.md#class-httpserverresponse
[`Temporal`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
[`Writable`]: stream.md#class-streamwritable
[`child_process`]: child_process.md
[`cipher.getAuthTag()`]: crypto.md#ciphergetauthtag
Expand Down
37 changes: 33 additions & 4 deletions doc/api/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4799,7 +4799,11 @@ Stats {
atime: 2019-06-22T03:37:33.072Z,
mtime: 2019-06-22T03:36:54.583Z,
ctime: 2019-06-22T03:37:06.624Z,
birthtime: 2019-06-22T03:28:46.937Z
birthtime: 2019-06-22T03:28:46.937Z,
atimeInstant: 2019-06-22T03:37:33.071963Z,
mtimeInstant: 2019-06-22T03:36:54.5833518Z,
ctimeInstant: 2019-06-22T03:37:06.6235366Z,
birthtimeInstant: 2019-06-22T03:28:46.9372893Z
}
false
Stats {
Expand All @@ -4820,7 +4824,11 @@ Stats {
atime: 2019-06-22T03:36:56.619Z,
mtime: 2019-06-22T03:36:54.584Z,
ctime: 2019-06-22T03:36:54.584Z,
birthtime: 2019-06-22T03:26:47.711Z
birthtime: 2019-06-22T03:26:47.711Z,
atimeInstant: 2019-06-22T03:36:56.6188555Z,
mtimeInstant: 2019-06-22T03:36:54.584Z,
ctimeInstant: 2019-06-22T03:36:54.5838145Z,
birthtimeInstant: 2019-06-22T03:26:47.7107478Z
}
```

Expand Down Expand Up @@ -7525,6 +7533,9 @@ i.e. before the `'ready'` event is emitted.
<!-- YAML
added: v0.1.21
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60789
description: Added `Temporal.Instant` support.
- version:
- v22.0.0
- v20.13.0
Expand Down Expand Up @@ -7560,10 +7571,19 @@ Stats {
mtimeMs: 1318289051000.1,
ctimeMs: 1318289051000.1,
birthtimeMs: 1318289051000.1,

// Instances of Date
atime: Mon, 10 Oct 2011 23:24:11 GMT,
mtime: Mon, 10 Oct 2011 23:24:11 GMT,
ctime: Mon, 10 Oct 2011 23:24:11 GMT,
birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
birthtime: Mon, 10 Oct 2011 23:24:11 GMT,

// Instances of Temporal.Instant
atimeInstant: 2011-10-10T23:24:11.0001Z,
mtimeInstant: 2011-10-10T23:24:11.0001Z,
ctimeInstant: 2011-10-10T23:24:11.0001Z,
birthtimeInstant: 2011-10-10T23:24:11.0001Z
}
```

`bigint` version:
Expand All @@ -7588,10 +7608,19 @@ BigIntStats {
mtimeNs: 1318289051000000000n,
ctimeNs: 1318289051000000000n,
birthtimeNs: 1318289051000000000n,

// Instances of Date
atime: Mon, 10 Oct 2011 23:24:11 GMT,
mtime: Mon, 10 Oct 2011 23:24:11 GMT,
ctime: Mon, 10 Oct 2011 23:24:11 GMT,
birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
birthtime: Mon, 10 Oct 2011 23:24:11 GMT,

// Instances of Temporal.Instant
atimeInstant: 2011-10-10T23:24:11Z,
mtimeInstant: 2011-10-10T23:24:11Z,
ctimeInstant: 2011-10-10T23:24:11Z,
birthtimeInstant: 2011-10-10T23:24:11Z
}
```

#### `stats.isBlockDevice()`
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,8 @@ E('ERR_NO_CRYPTO',
'Node.js is not compiled with OpenSSL crypto support', Error);
E('ERR_NO_ICU',
'%s is not supported on Node.js compiled without ICU', TypeError);
E('ERR_NO_TEMPORAL',
'Node.js is not compiled with Temporal support', Error);
E('ERR_NO_TYPESCRIPT',
'Node.js is not compiled with TypeScript support', Error);
E('ERR_OPERATION_FAILED', 'Operation failed: %s', Error, TypeError);
Expand Down
154 changes: 143 additions & 11 deletions lib/internal/fs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
DatePrototypeGetTime,
ErrorCaptureStackTrace,
FunctionPrototypeCall,
MathFloor,
MathMin,
MathRound,
Number,
Expand All @@ -22,6 +23,7 @@ const {
Symbol,
TypedArrayPrototypeAt,
TypedArrayPrototypeIncludes,
globalThis,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
globalThis,
globalThis: {
Temporal,
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this doesn't seem to work since at this point of bootstrapping Temporal is not defined yet.
Same goes for const { Temporal } = globalThis; on top level of the file.

} = primordials;

const { Buffer } = require('buffer');
Expand All @@ -32,6 +34,7 @@ const {
ERR_INCOMPATIBLE_OPTION_PAIR,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_NO_TEMPORAL,
ERR_OUT_OF_RANGE,
},
hideStackFrames,
Expand All @@ -43,10 +46,10 @@ const {
isUint8Array,
} = require('internal/util/types');
const {
kEmptyObject,
once,
deprecate,
isWindows,
kEmptyObject,
once,
setOwnProperty,
} = require('internal/util');
const { toPathIfFileURL } = require('internal/url');
Expand All @@ -62,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 {
Expand Down Expand Up @@ -430,6 +437,25 @@ function nsFromTimeSpecBigInt(sec, nsec) {
return sec * kNsPerSecBigInt + nsec;
}

// TODO(LiviaMedeiros): TemporalInstant primordial
let TemporalInstant;

function instantFromNs(nsec) {
TemporalInstant ??= globalThis.Temporal?.Instant;
if (TemporalInstant === undefined) {
throw new ERR_NO_TEMPORAL();
}
return new TemporalInstant(nsec);
}

function instantFromTimeSpecMs(msec, nsec) {
TemporalInstant ??= globalThis.Temporal?.Instant;
if (TemporalInstant === undefined) {
throw new ERR_NO_TEMPORAL();
}
return new TemporalInstant(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
Expand Down Expand Up @@ -490,6 +516,106 @@ const lazyDateFields = {
},
};

const lazyTemporalFields = {
__proto__: null,
atimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'atimeInstant',
instantFromTimeSpecMs(this.atimeMs, this[kPartialAtimeNs]));
Comment thread
aduh95 marked this conversation as resolved.
},
set(value) {
setOwnProperty(this, 'atimeInstant', value);
},
},
mtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'mtimeInstant',
instantFromTimeSpecMs(this.mtimeMs, this[kPartialMtimeNs]));
},
set(value) {
setOwnProperty(this, 'mtimeInstant', value);
},
},
ctimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'ctimeInstant',
instantFromTimeSpecMs(this.ctimeMs, this[kPartialCtimeNs]));
},
set(value) {
setOwnProperty(this, 'ctimeInstant', value);
},
},
birthtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'birthtimeInstant',
instantFromTimeSpecMs(this.birthtimeMs, this[kPartialBirthtimeNs]));
},
set(value) {
setOwnProperty(this, 'birthtimeInstant', value);
},
},
};

const lazyTemporalBigIntFields = {
__proto__: null,
atimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'atimeInstant', instantFromNs(this.atimeNs));
},
set(value) {
setOwnProperty(this, 'atimeInstant', value);
},
},
mtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'mtimeInstant', instantFromNs(this.mtimeNs));
},
set(value) {
setOwnProperty(this, 'mtimeInstant', value);
},
},
ctimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'ctimeInstant', instantFromNs(this.ctimeNs));
},
set(value) {
setOwnProperty(this, 'ctimeInstant', value);
},
},
birthtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
return setOwnProperty(this, 'birthtimeInstant', instantFromNs(this.birthtimeNs));
},
set(value) {
setOwnProperty(this, 'birthtimeInstant', value);
},
},
};

function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize,
ino, size, blocks,
atimeNs, mtimeNs, ctimeNs, birthtimeNs) {
Expand All @@ -508,6 +634,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 ||
Expand All @@ -519,18 +646,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 ||
Expand Down Expand Up @@ -563,10 +695,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
);
}

Expand Down
Loading
Loading