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
167 changes: 156 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 @@ -23,6 +24,7 @@ const {
Symbol,
TypedArrayPrototypeAt,
TypedArrayPrototypeIncludes,
globalThis,
} = primordials;

const { Buffer } = require('buffer');
Expand All @@ -33,6 +35,7 @@ const {
ERR_INCOMPATIBLE_OPTION_PAIR,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_NO_TEMPORAL,
ERR_OUT_OF_RANGE,
},
hideStackFrames,
Expand All @@ -44,10 +47,11 @@ const {
isUint8Array,
} = require('internal/util/types');
const {
kEmptyObject,
once,
deprecate,
isWindows,
kEmptyObject,
once,
setOwnProperty,
} = require('internal/util');
const { toPathIfFileURL } = require('internal/url');
const {
Expand All @@ -62,6 +66,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 +438,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 +517,118 @@ const lazyDateFields = {
},
};

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

const lazyTemporalBigIntFields = {
__proto__: null,
atimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
const value = instantFromNs(this.atimeNs);
setOwnProperty(this, 'atimeInstant', value);
return value;
},
set(value) {
setOwnProperty(this, 'atimeInstant', value);
},
},
mtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
const value = instantFromNs(this.mtimeNs);
setOwnProperty(this, 'mtimeInstant', value);
return value;
},
set(value) {
setOwnProperty(this, 'mtimeInstant', value);
},
},
ctimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
const value = instantFromNs(this.ctimeNs);
setOwnProperty(this, 'ctimeInstant', value);
return value;
},
set(value) {
setOwnProperty(this, 'ctimeInstant', value);
},
},
birthtimeInstant: {
__proto__: null,
enumerable: true,
configurable: true,
get() {
const value = instantFromNs(this.birthtimeNs);
setOwnProperty(this, 'birthtimeInstant', value);
return value;
},
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 +647,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 +659,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 +708,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