chronokinesis 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +22 -3
- package/dist/chronokinesis.cjs +48 -7
- package/dist/index.cjs +48 -7
- package/index.js +48 -7
- package/package.json +15 -10
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## v8.1.0 - 2026-09-20
|
|
6
|
+
|
|
7
|
+
- mock native `Temporal.Now` (Node >= 26) alongside `Date`, `Temporal.Now.timeZoneId()` honours timezone travel
|
|
8
|
+
|
|
9
|
+
## v8.0.1 - 2026-09-13
|
|
10
|
+
|
|
11
|
+
- use nullish coalescing and optional chaining internally, browser bundle now requires ES2020
|
|
12
|
+
- replace `markdown-toc` script with `@0dep/toc`
|
|
13
|
+
- drop build with node v18 due to dev deps
|
|
14
|
+
|
|
15
|
+
## v8.0.0 - 2026-04-24
|
|
16
|
+
|
|
17
|
+
### Breaking
|
|
18
|
+
|
|
19
|
+
- mocks `process.hrtime([time])` and `process.hrtime.bigint()`
|
|
20
|
+
- mocks `performance.now()`
|
|
21
|
+
|
|
22
|
+
### Fixes
|
|
23
|
+
|
|
24
|
+
- fix bug in travel that resulted in consumed milliseconds before returning
|
|
25
|
+
|
|
26
|
+
## v7.0.1 - 2025-11-13
|
|
27
|
+
|
|
28
|
+
- proof of provenance release
|
|
29
|
+
|
|
30
|
+
## v7.0.0 - 2025-07-25
|
|
31
|
+
|
|
32
|
+
### Breaking
|
|
33
|
+
|
|
34
|
+
- when declaring "exports" field in package.json it takes prescedence over "main", thus breaking the exports default. Use `import * as ck from 'chronokinesis';`. A simple search & replace should fix this.
|
|
35
|
+
|
|
36
|
+
### Fixes
|
|
37
|
+
|
|
38
|
+
- attempt to mitigate issue #4 - multiple module load
|
|
39
|
+
- export FakeDate
|
|
40
|
+
- test faking dates with luxon
|
|
41
|
+
- use prettier for formatting rules
|
|
42
|
+
- use texample to run through README examples
|
|
43
|
+
|
|
44
|
+
## v6.0.0 - 2023-08-09
|
|
45
|
+
|
|
46
|
+
### Breaking
|
|
47
|
+
|
|
48
|
+
- timezone function calls travel by default #3
|
|
49
|
+
- timezone function signature also takes travel arguments
|
|
50
|
+
|
|
51
|
+
## v5.0.0 - 2023-04-10
|
|
52
|
+
|
|
53
|
+
- export as module with dist for require and umd
|
|
54
|
+
|
|
55
|
+
## v4.0.1 - 2022-12-09
|
|
56
|
+
|
|
57
|
+
- replace lab with mocha and chai
|
|
58
|
+
- default to node v14
|
|
59
|
+
- stop building node v10
|
|
60
|
+
- bump babel and rollup
|
|
61
|
+
- use c8 for coverage
|
package/README.md
CHANGED
|
@@ -24,11 +24,12 @@ Mock time and date for traveling and freezing. Inspired and borrowed from [timek
|
|
|
24
24
|
- [Nodejs require](#nodejs-require)
|
|
25
25
|
- [Browser (UMD)](#browser-umd)
|
|
26
26
|
- [High-resolution clocks](#high-resolution-clocks)
|
|
27
|
+
- [Temporal](#temporal)
|
|
27
28
|
- [chronokinesis vs `node:test` mock timers](#chronokinesis-vs-nodetest-mock-timers)
|
|
28
29
|
- [Caveats when mocking high-resolution clocks](#caveats-when-mocking-high-resolution-clocks)
|
|
29
30
|
- [Acknowledgements](#acknowledgements)
|
|
30
31
|
|
|
31
|
-
<!--
|
|
32
|
+
<!-- /toc -->
|
|
32
33
|
|
|
33
34
|
## Introduction
|
|
34
35
|
|
|
@@ -132,7 +133,7 @@ setTimeout(function () {
|
|
|
132
133
|
}, 1500);
|
|
133
134
|
```
|
|
134
135
|
|
|
135
|
-
When used in combination with [`freeze`](#
|
|
136
|
+
When used in combination with [`freeze`](#freezeargs) the time is still frozen but at the travelled time().
|
|
136
137
|
|
|
137
138
|
```javascript
|
|
138
139
|
import * as ck from 'chronokinesis';
|
|
@@ -293,9 +294,27 @@ console.log(performance.now() - basePerf); // ≈ 1000 (ms)
|
|
|
293
294
|
ck.reset();
|
|
294
295
|
```
|
|
295
296
|
|
|
297
|
+
## Temporal
|
|
298
|
+
|
|
299
|
+
When the runtime ships a native `Temporal` global (Node ≥ 26), the methods on `Temporal.Now` are patched in place while timekeeping is active, so `Temporal.Now.instant()` and friends follow the same frozen or travelled clock as `Date.now()`. `Temporal.Now.timeZoneId()` returns the travelled IANA zone while a [timezone traveller](#timezonetimezone-args) is active, so the zone-less variants (`zonedDateTimeISO()`, `plainDateTimeISO()`, `plainDateISO()`, `plainTimeISO()`) resolve in that zone. `reset()` restores the native methods by identity.
|
|
300
|
+
|
|
301
|
+
Temporal polyfills that build `Temporal.Now` on top of `Date.now()` need no patching and keep working on older Node versions. Polyfills that prefer the native global when present pick up the mock automatically.
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
import * as ck from 'chronokinesis';
|
|
305
|
+
|
|
306
|
+
ck.timezone('Asia/Tokyo').freeze(1980, 0, 1, 12, 0);
|
|
307
|
+
|
|
308
|
+
console.log(Temporal.Now.timeZoneId()); // Asia/Tokyo
|
|
309
|
+
console.log(Temporal.Now.plainDateTimeISO().toString()); // 1980-01-01T12:00:00
|
|
310
|
+
console.log(Temporal.Now.instant().epochMilliseconds === Date.now()); // true
|
|
311
|
+
|
|
312
|
+
ck.reset();
|
|
313
|
+
```
|
|
314
|
+
|
|
296
315
|
## chronokinesis vs `node:test` mock timers
|
|
297
316
|
|
|
298
|
-
chronokinesis mocks **clocks only** — `Date`, `process.hrtime`, `performance.now`. Timers (`setTimeout`, `setInterval`, `setImmediate`) still run on the real wall clock; a `setTimeout(fn, 10)` under `freeze()` still fires ~10ms later in real time.
|
|
317
|
+
chronokinesis mocks **clocks only** — `Date`, `process.hrtime`, `performance.now`, and native `Temporal.Now`. Timers (`setTimeout`, `setInterval`, `setImmediate`) still run on the real wall clock; a `setTimeout(fn, 10)` under `freeze()` still fires ~10ms later in real time.
|
|
299
318
|
|
|
300
319
|
Node's built-in `node:test` provides `mock.timers` which is different: it mocks both the clock **and** the timer queue, and `mock.timers.tick(ms)` synchronously advances time and fires any timers scheduled within that window — no real waiting required.
|
|
301
320
|
|
package/dist/chronokinesis.cjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
14
14
|
|
|
15
|
-
const NativeDate = Date[kNativeDate]
|
|
15
|
+
const NativeDate = Date[kNativeDate] ?? Date;
|
|
16
16
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
17
17
|
|
|
18
18
|
/* c8 ignore start -- environment-capability guards; false branches only hit in browser (isomorphic test) */
|
|
@@ -21,12 +21,16 @@
|
|
|
21
21
|
const nativeHrtimeBigint = nativeHrtime && typeof nativeHrtime.bigint === 'function' ? nativeHrtime.bigint : null;
|
|
22
22
|
const nativePerformance = typeof performance !== 'undefined' ? performance : null;
|
|
23
23
|
const nativePerformanceNow = nativePerformance && typeof nativePerformance.now === 'function' ? nativePerformance.now : null;
|
|
24
|
+
// Native Temporal (Node >= 26) reads the OS clock directly in Temporal.Now, so any Temporal global
|
|
25
|
+
// present at load is patched in place alongside Date. Polyfills built on Date.now() would work unpatched.
|
|
26
|
+
const nativeTemporal = typeof Temporal !== 'undefined' && typeof Temporal.Now === 'object' ? Temporal : null;
|
|
27
|
+
const nativeTemporalNow = nativeTemporal && snapshotTemporalNow(nativeTemporal.Now);
|
|
24
28
|
|
|
25
29
|
// Anchor native perf.now against native hrtime at module load so that later reads
|
|
26
30
|
// can reconstruct real native perf.now even when process.hrtime has been swapped
|
|
27
31
|
// (Node <22 wires performance.now to process.hrtime internally).
|
|
28
|
-
const perfAnchorMs = nativePerformanceNow
|
|
29
|
-
const hrtimeAnchorNs = nativeHrtimeBigint
|
|
32
|
+
const perfAnchorMs = nativePerformanceNow?.call(nativePerformance) ?? 0;
|
|
33
|
+
const hrtimeAnchorNs = nativeHrtimeBigint?.call(nativeProcess) ?? 0n;
|
|
30
34
|
/* c8 ignore stop */
|
|
31
35
|
|
|
32
36
|
let freezedAt = null;
|
|
@@ -190,6 +194,7 @@
|
|
|
190
194
|
if (nativePerformanceNow) {
|
|
191
195
|
Object.defineProperty(nativePerformance, 'now', { value: fakePerformanceNow, configurable: true, writable: true });
|
|
192
196
|
}
|
|
197
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, fakeTemporalNow());
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
function useNativeDate() {
|
|
@@ -198,6 +203,7 @@
|
|
|
198
203
|
if (nativePerformanceNow) {
|
|
199
204
|
Object.defineProperty(nativePerformance, 'now', { value: nativePerformanceNow, configurable: true, writable: true });
|
|
200
205
|
}
|
|
206
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, {});
|
|
201
207
|
}
|
|
202
208
|
|
|
203
209
|
function time() {
|
|
@@ -231,8 +237,7 @@
|
|
|
231
237
|
}
|
|
232
238
|
|
|
233
239
|
function fakeHrtimeNs() {
|
|
234
|
-
|
|
235
|
-
return nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
240
|
+
return freezedHrtimeNs ?? nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
236
241
|
}
|
|
237
242
|
|
|
238
243
|
function fakeHrtime(prev) {
|
|
@@ -254,8 +259,44 @@
|
|
|
254
259
|
};
|
|
255
260
|
|
|
256
261
|
function fakePerformanceNow() {
|
|
257
|
-
|
|
258
|
-
|
|
262
|
+
return freezedPerformanceNow ?? nativePerformanceNowFromHrtime() + performanceNowOffset;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function snapshotTemporalNow(Now) {
|
|
266
|
+
const snapshot = {};
|
|
267
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(Now))) {
|
|
268
|
+
if (typeof descriptor.value === 'function') snapshot[key] = descriptor;
|
|
269
|
+
}
|
|
270
|
+
return snapshot;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function assignTemporalNow(Now, methods) {
|
|
274
|
+
for (const [key, descriptor] of Object.entries(nativeTemporalNow)) {
|
|
275
|
+
Object.defineProperty(Now, key, { ...descriptor, value: methods[key] ?? descriptor.value });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function fakeTemporalNow() {
|
|
280
|
+
return {
|
|
281
|
+
instant: fakeTemporalInstant,
|
|
282
|
+
timeZoneId: fakeTemporalTimeZoneId,
|
|
283
|
+
zonedDateTimeISO: fakeTemporalZonedDateTimeISO,
|
|
284
|
+
plainDateTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDateTime(),
|
|
285
|
+
plainDateISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDate(),
|
|
286
|
+
plainTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainTime(),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function fakeTemporalInstant() {
|
|
291
|
+
return nativeTemporal.Instant.fromEpochMilliseconds(currentMockedMs());
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function fakeTemporalTimeZoneId() {
|
|
295
|
+
return iana ?? nativeTemporalNow.timeZoneId.value.call(nativeTemporal.Now);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function fakeTemporalZonedDateTimeISO(timeZone) {
|
|
299
|
+
return fakeTemporalInstant().toZonedDateTimeISO(timeZone ?? fakeTemporalTimeZoneId());
|
|
259
300
|
}
|
|
260
301
|
|
|
261
302
|
function instantiate(type, args) {
|
package/dist/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
10
10
|
|
|
11
|
-
const NativeDate = Date[kNativeDate]
|
|
11
|
+
const NativeDate = Date[kNativeDate] ?? Date;
|
|
12
12
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
13
13
|
|
|
14
14
|
/* c8 ignore start -- environment-capability guards; false branches only hit in browser (isomorphic test) */
|
|
@@ -17,12 +17,16 @@ const nativeHrtime = nativeProcess && typeof nativeProcess.hrtime === 'function'
|
|
|
17
17
|
const nativeHrtimeBigint = nativeHrtime && typeof nativeHrtime.bigint === 'function' ? nativeHrtime.bigint : null;
|
|
18
18
|
const nativePerformance = typeof performance !== 'undefined' ? performance : null;
|
|
19
19
|
const nativePerformanceNow = nativePerformance && typeof nativePerformance.now === 'function' ? nativePerformance.now : null;
|
|
20
|
+
// Native Temporal (Node >= 26) reads the OS clock directly in Temporal.Now, so any Temporal global
|
|
21
|
+
// present at load is patched in place alongside Date. Polyfills built on Date.now() would work unpatched.
|
|
22
|
+
const nativeTemporal = typeof Temporal !== 'undefined' && typeof Temporal.Now === 'object' ? Temporal : null;
|
|
23
|
+
const nativeTemporalNow = nativeTemporal && snapshotTemporalNow(nativeTemporal.Now);
|
|
20
24
|
|
|
21
25
|
// Anchor native perf.now against native hrtime at module load so that later reads
|
|
22
26
|
// can reconstruct real native perf.now even when process.hrtime has been swapped
|
|
23
27
|
// (Node <22 wires performance.now to process.hrtime internally).
|
|
24
|
-
const perfAnchorMs = nativePerformanceNow
|
|
25
|
-
const hrtimeAnchorNs = nativeHrtimeBigint
|
|
28
|
+
const perfAnchorMs = nativePerformanceNow?.call(nativePerformance) ?? 0;
|
|
29
|
+
const hrtimeAnchorNs = nativeHrtimeBigint?.call(nativeProcess) ?? 0n;
|
|
26
30
|
/* c8 ignore stop */
|
|
27
31
|
|
|
28
32
|
let freezedAt = null;
|
|
@@ -186,6 +190,7 @@ function useFakeDate() {
|
|
|
186
190
|
if (nativePerformanceNow) {
|
|
187
191
|
Object.defineProperty(nativePerformance, 'now', { value: fakePerformanceNow, configurable: true, writable: true });
|
|
188
192
|
}
|
|
193
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, fakeTemporalNow());
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
function useNativeDate() {
|
|
@@ -194,6 +199,7 @@ function useNativeDate() {
|
|
|
194
199
|
if (nativePerformanceNow) {
|
|
195
200
|
Object.defineProperty(nativePerformance, 'now', { value: nativePerformanceNow, configurable: true, writable: true });
|
|
196
201
|
}
|
|
202
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, {});
|
|
197
203
|
}
|
|
198
204
|
|
|
199
205
|
function time() {
|
|
@@ -227,8 +233,7 @@ function shiftAndLockFakeClocks(deltaMs) {
|
|
|
227
233
|
}
|
|
228
234
|
|
|
229
235
|
function fakeHrtimeNs() {
|
|
230
|
-
|
|
231
|
-
return nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
236
|
+
return freezedHrtimeNs ?? nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
232
237
|
}
|
|
233
238
|
|
|
234
239
|
function fakeHrtime(prev) {
|
|
@@ -250,8 +255,44 @@ fakeHrtime.bigint = function fakeHrtimeBigint() {
|
|
|
250
255
|
};
|
|
251
256
|
|
|
252
257
|
function fakePerformanceNow() {
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
return freezedPerformanceNow ?? nativePerformanceNowFromHrtime() + performanceNowOffset;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function snapshotTemporalNow(Now) {
|
|
262
|
+
const snapshot = {};
|
|
263
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(Now))) {
|
|
264
|
+
if (typeof descriptor.value === 'function') snapshot[key] = descriptor;
|
|
265
|
+
}
|
|
266
|
+
return snapshot;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function assignTemporalNow(Now, methods) {
|
|
270
|
+
for (const [key, descriptor] of Object.entries(nativeTemporalNow)) {
|
|
271
|
+
Object.defineProperty(Now, key, { ...descriptor, value: methods[key] ?? descriptor.value });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function fakeTemporalNow() {
|
|
276
|
+
return {
|
|
277
|
+
instant: fakeTemporalInstant,
|
|
278
|
+
timeZoneId: fakeTemporalTimeZoneId,
|
|
279
|
+
zonedDateTimeISO: fakeTemporalZonedDateTimeISO,
|
|
280
|
+
plainDateTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDateTime(),
|
|
281
|
+
plainDateISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDate(),
|
|
282
|
+
plainTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainTime(),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function fakeTemporalInstant() {
|
|
287
|
+
return nativeTemporal.Instant.fromEpochMilliseconds(currentMockedMs());
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function fakeTemporalTimeZoneId() {
|
|
291
|
+
return iana ?? nativeTemporalNow.timeZoneId.value.call(nativeTemporal.Now);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function fakeTemporalZonedDateTimeISO(timeZone) {
|
|
295
|
+
return fakeTemporalInstant().toZonedDateTimeISO(timeZone ?? fakeTemporalTimeZoneId());
|
|
255
296
|
}
|
|
256
297
|
|
|
257
298
|
function instantiate(type, args) {
|
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
const kNativeDate = Symbol.for('chronokinesis native date');
|
|
8
8
|
|
|
9
|
-
const NativeDate = Date[kNativeDate]
|
|
9
|
+
const NativeDate = Date[kNativeDate] ?? Date;
|
|
10
10
|
const nativeGetTimezoneOffset = NativeDate.prototype.getTimezoneOffset;
|
|
11
11
|
|
|
12
12
|
/* c8 ignore start -- environment-capability guards; false branches only hit in browser (isomorphic test) */
|
|
@@ -15,12 +15,16 @@ const nativeHrtime = nativeProcess && typeof nativeProcess.hrtime === 'function'
|
|
|
15
15
|
const nativeHrtimeBigint = nativeHrtime && typeof nativeHrtime.bigint === 'function' ? nativeHrtime.bigint : null;
|
|
16
16
|
const nativePerformance = typeof performance !== 'undefined' ? performance : null;
|
|
17
17
|
const nativePerformanceNow = nativePerformance && typeof nativePerformance.now === 'function' ? nativePerformance.now : null;
|
|
18
|
+
// Native Temporal (Node >= 26) reads the OS clock directly in Temporal.Now, so any Temporal global
|
|
19
|
+
// present at load is patched in place alongside Date. Polyfills built on Date.now() would work unpatched.
|
|
20
|
+
const nativeTemporal = typeof Temporal !== 'undefined' && typeof Temporal.Now === 'object' ? Temporal : null;
|
|
21
|
+
const nativeTemporalNow = nativeTemporal && snapshotTemporalNow(nativeTemporal.Now);
|
|
18
22
|
|
|
19
23
|
// Anchor native perf.now against native hrtime at module load so that later reads
|
|
20
24
|
// can reconstruct real native perf.now even when process.hrtime has been swapped
|
|
21
25
|
// (Node <22 wires performance.now to process.hrtime internally).
|
|
22
|
-
const perfAnchorMs = nativePerformanceNow
|
|
23
|
-
const hrtimeAnchorNs = nativeHrtimeBigint
|
|
26
|
+
const perfAnchorMs = nativePerformanceNow?.call(nativePerformance) ?? 0;
|
|
27
|
+
const hrtimeAnchorNs = nativeHrtimeBigint?.call(nativeProcess) ?? 0n;
|
|
24
28
|
/* c8 ignore stop */
|
|
25
29
|
|
|
26
30
|
let freezedAt = null;
|
|
@@ -184,6 +188,7 @@ function useFakeDate() {
|
|
|
184
188
|
if (nativePerformanceNow) {
|
|
185
189
|
Object.defineProperty(nativePerformance, 'now', { value: fakePerformanceNow, configurable: true, writable: true });
|
|
186
190
|
}
|
|
191
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, fakeTemporalNow());
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
function useNativeDate() {
|
|
@@ -192,6 +197,7 @@ function useNativeDate() {
|
|
|
192
197
|
if (nativePerformanceNow) {
|
|
193
198
|
Object.defineProperty(nativePerformance, 'now', { value: nativePerformanceNow, configurable: true, writable: true });
|
|
194
199
|
}
|
|
200
|
+
if (nativeTemporalNow) assignTemporalNow(nativeTemporal.Now, {});
|
|
195
201
|
}
|
|
196
202
|
|
|
197
203
|
function time() {
|
|
@@ -225,8 +231,7 @@ function shiftAndLockFakeClocks(deltaMs) {
|
|
|
225
231
|
}
|
|
226
232
|
|
|
227
233
|
function fakeHrtimeNs() {
|
|
228
|
-
|
|
229
|
-
return nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
234
|
+
return freezedHrtimeNs ?? nativeHrtimeBigint.call(nativeProcess) + hrtimeOffset;
|
|
230
235
|
}
|
|
231
236
|
|
|
232
237
|
function fakeHrtime(prev) {
|
|
@@ -248,8 +253,44 @@ fakeHrtime.bigint = function fakeHrtimeBigint() {
|
|
|
248
253
|
};
|
|
249
254
|
|
|
250
255
|
function fakePerformanceNow() {
|
|
251
|
-
|
|
252
|
-
|
|
256
|
+
return freezedPerformanceNow ?? nativePerformanceNowFromHrtime() + performanceNowOffset;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function snapshotTemporalNow(Now) {
|
|
260
|
+
const snapshot = {};
|
|
261
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(Now))) {
|
|
262
|
+
if (typeof descriptor.value === 'function') snapshot[key] = descriptor;
|
|
263
|
+
}
|
|
264
|
+
return snapshot;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function assignTemporalNow(Now, methods) {
|
|
268
|
+
for (const [key, descriptor] of Object.entries(nativeTemporalNow)) {
|
|
269
|
+
Object.defineProperty(Now, key, { ...descriptor, value: methods[key] ?? descriptor.value });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function fakeTemporalNow() {
|
|
274
|
+
return {
|
|
275
|
+
instant: fakeTemporalInstant,
|
|
276
|
+
timeZoneId: fakeTemporalTimeZoneId,
|
|
277
|
+
zonedDateTimeISO: fakeTemporalZonedDateTimeISO,
|
|
278
|
+
plainDateTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDateTime(),
|
|
279
|
+
plainDateISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainDate(),
|
|
280
|
+
plainTimeISO: (timeZone) => fakeTemporalZonedDateTimeISO(timeZone).toPlainTime(),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function fakeTemporalInstant() {
|
|
285
|
+
return nativeTemporal.Instant.fromEpochMilliseconds(currentMockedMs());
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function fakeTemporalTimeZoneId() {
|
|
289
|
+
return iana ?? nativeTemporalNow.timeZoneId.value.call(nativeTemporal.Now);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function fakeTemporalZonedDateTimeISO(timeZone) {
|
|
293
|
+
return fakeTemporalInstant().toZonedDateTimeISO(timeZone ?? fakeTemporalTimeZoneId());
|
|
253
294
|
}
|
|
254
295
|
|
|
255
296
|
function instantiate(type, args) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chronokinesis",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.1.0",
|
|
4
4
|
"description": "Module for testing time-dependent code",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Pål Edman",
|
|
@@ -23,20 +23,21 @@
|
|
|
23
23
|
"types": "./index.d.ts"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"toc": "node generate-api-toc.cjs",
|
|
27
26
|
"test": "mocha",
|
|
27
|
+
"posttest": "npm run lint && npm run dist && texample -g",
|
|
28
28
|
"lint": "eslint . --cache && prettier . --check --cache",
|
|
29
29
|
"test:lcov": "c8 -r lcov -r text mocha && npm run lint",
|
|
30
30
|
"cov:html": "c8 mocha -R dot && c8 report --reporter html",
|
|
31
|
-
"posttest": "npm run lint && npm run dist && texample -g",
|
|
32
31
|
"prepack": "npm run dist",
|
|
32
|
+
"toc": "toc -c README.md",
|
|
33
33
|
"dist": "npm run toc && rollup -c"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"index.js",
|
|
37
37
|
"index.d.ts",
|
|
38
38
|
"dist/chronokinesis.cjs",
|
|
39
|
-
"dist/index.cjs"
|
|
39
|
+
"dist/index.cjs",
|
|
40
|
+
"CHANGELOG.md"
|
|
40
41
|
],
|
|
41
42
|
"bugs": {
|
|
42
43
|
"url": "https://github.com/paed01/chronokinesis/issues"
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"time",
|
|
47
48
|
"hrtime",
|
|
48
49
|
"performance",
|
|
50
|
+
"temporal",
|
|
49
51
|
"timezone",
|
|
50
52
|
"fake",
|
|
51
53
|
"mock",
|
|
@@ -56,18 +58,21 @@
|
|
|
56
58
|
"fake now"
|
|
57
59
|
],
|
|
58
60
|
"devDependencies": {
|
|
61
|
+
"@0dep/toc": "^2.1.0",
|
|
62
|
+
"@eslint/js": "^10.0.1",
|
|
63
|
+
"@js-temporal/polyfill": "^0.5.1",
|
|
59
64
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
60
|
-
"c8": "^
|
|
65
|
+
"c8": "^12.0.0",
|
|
61
66
|
"chai": "^6.2.0",
|
|
62
|
-
"eslint": "^
|
|
63
|
-
"
|
|
67
|
+
"eslint": "^10.10.0",
|
|
68
|
+
"globals": "^17.12.0",
|
|
69
|
+
"happy-dom": "^20.14.5",
|
|
64
70
|
"lodash.clonedeep": "^4.5.0",
|
|
65
71
|
"luxon": "^3.7.1",
|
|
66
|
-
"
|
|
67
|
-
"mocha": "^11.0.1",
|
|
72
|
+
"mocha": "^12.0.1",
|
|
68
73
|
"moment": "^2.30.1",
|
|
69
74
|
"prettier": "^3.2.5",
|
|
70
75
|
"rollup": "^4.12.1",
|
|
71
|
-
"texample": "^
|
|
76
|
+
"texample": "^1.0.2"
|
|
72
77
|
}
|
|
73
78
|
}
|