From ab53e9db11895ebeddc3a42335ca40c2097f8d81 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Sun, 1 Jan 2023 21:08:06 -0600 Subject: user/node: Fix time64 issue on pmmx This patch reverts Node MR 43714[1], which broke time64 on pmmx. [1]: https://github.com/nodejs/node/pull/43714 Fixes: #935 --- user/node/pmmx-time64.patch | 204 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 user/node/pmmx-time64.patch (limited to 'user/node/pmmx-time64.patch') diff --git a/user/node/pmmx-time64.patch b/user/node/pmmx-time64.patch new file mode 100644 index 000000000..4e92cd78c --- /dev/null +++ b/user/node/pmmx-time64.patch @@ -0,0 +1,204 @@ +--- node-v18.12.1/lib/internal/fs/utils.js.old 2022-11-04 11:13:14.000000000 -0500 ++++ node-v18.12.1/lib/internal/fs/utils.js 2023-01-01 18:07:20.292441829 -0600 +@@ -12,7 +12,6 @@ + NumberIsFinite, + NumberIsInteger, + MathMin, +- MathRound, + ObjectIs, + ObjectPrototypeHasOwnProperty, + ObjectSetPrototypeOf, +@@ -40,7 +39,7 @@ + } = require('internal/errors'); + const { + isArrayBufferView, +- isBigInt64Array, ++ isBigUint64Array, + isDate, + isUint8Array, + } = require('internal/util/types'); +@@ -455,16 +454,14 @@ + return sec * kNsPerSecBigInt + nsec; + } + +-// The Date constructor performs Math.floor() on the absolute value +-// of the timestamp: https://tc39.es/ecma262/#sec-timeclip ++// The Date constructor performs Math.floor() to the timestamp. ++// https://tc39.es/ecma262/#sec-timeclip + // Since there may be a precision loss when the timestamp is + // converted to a floating point number, we manually round + // the timestamp here before passing it to Date(). + // Refs: https://github.com/nodejs/node/pull/12607 +-// Refs: https://github.com/nodejs/node/pull/43714 + function dateFromMs(ms) { +- // Coercing to number, ms can be bigint +- return new Date(MathRound(Number(ms))); ++ return new Date(Number(ms) + 0.5); + } + + function BigIntStats(dev, mode, nlink, uid, gid, rdev, blksize, +@@ -529,12 +526,12 @@ + }; + + /** +- * @param {Float64Array | BigInt64Array} stats ++ * @param {Float64Array | BigUint64Array} stats + * @param {number} offset + * @returns {BigIntStats | Stats} + */ + function getStatsFromBinding(stats, offset = 0) { +- if (isBigInt64Array(stats)) { ++ if (isBigUint64Array(stats)) { + return new BigIntStats( + stats[0 + offset], stats[1 + offset], stats[2 + offset], + stats[3 + offset], stats[4 + offset], stats[5 + offset], +--- node-v18.12.1/src/aliased_buffer.h.old 2022-11-04 11:13:14.000000000 -0500 ++++ node-v18.12.1/src/aliased_buffer.h 2023-01-01 18:08:01.407999936 -0600 +@@ -306,7 +306,7 @@ + typedef AliasedBufferBase AliasedUint8Array; + typedef AliasedBufferBase AliasedUint32Array; + typedef AliasedBufferBase AliasedFloat64Array; +-typedef AliasedBufferBase AliasedBigInt64Array; ++typedef AliasedBufferBase AliasedBigUint64Array; + } // namespace node + + #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +--- node-v18.12.1/src/node_file-inl.h.old 2022-11-04 11:13:14.000000000 -0500 ++++ node-v18.12.1/src/node_file-inl.h 2023-01-01 18:09:07.830823990 -0600 +@@ -90,18 +90,9 @@ + fields->SetValue(offset + static_cast(FsStatsOffset::stat_offset), \ + static_cast(stat)) + +-// On win32, time is stored in uint64_t and starts from 1601-01-01. +-// libuv calculates tv_sec and tv_nsec from it and converts to signed long, +-// which causes Y2038 overflow. On the other platforms it is safe to treat +-// negative values as pre-epoch time. +-#ifdef _WIN32 + #define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ + /* NOLINTNEXTLINE(runtime/int) */ \ + SET_FIELD_WITH_STAT(stat_offset, static_cast(stat)) +-#else +-#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ +- SET_FIELD_WITH_STAT(stat_offset, static_cast(stat)) +-#endif // _WIN32 + + SET_FIELD_WITH_STAT(kDev, s->st_dev); + SET_FIELD_WITH_STAT(kMode, s->st_mode); +@@ -242,7 +233,7 @@ + Environment* env = binding_data->env(); + if (value->StrictEquals(env->fs_use_promises_symbol())) { + if (use_bigint) { +- return FSReqPromise::New(binding_data, use_bigint); ++ return FSReqPromise::New(binding_data, use_bigint); + } else { + return FSReqPromise::New(binding_data, use_bigint); + } +--- node-v18.12.1/src/node_file.h.old 2022-11-04 11:13:14.000000000 -0500 ++++ node-v18.12.1/src/node_file.h 2023-01-01 18:09:24.888981123 -0600 +@@ -18,7 +18,7 @@ + explicit BindingData(Environment* env, v8::Local wrap); + + AliasedFloat64Array stats_field_array; +- AliasedBigInt64Array stats_field_bigint_array; ++ AliasedBigUint64Array stats_field_bigint_array; + + std::vector> + file_handle_read_wrap_freelist; +--- node-v18.12.1/test/parallel/test-fs-stat-date.mjs.old 2022-11-04 11:13:14.000000000 -0500 ++++ node-v18.12.1/test/parallel/test-fs-stat-date.mjs 1969-12-31 18:00:00.000000000 -0600 +@@ -1,95 +0,0 @@ +-import * as common from '../common/index.mjs'; +- +-// Test timestamps returned by fsPromises.stat and fs.statSync +- +-import fs from 'node:fs'; +-import fsPromises from 'node:fs/promises'; +-import path from 'node:path'; +-import assert from 'node:assert'; +-import tmpdir from '../common/tmpdir.js'; +- +-// On some platforms (for example, ppc64) boundaries are tighter +-// than usual. If we catch these errors, skip corresponding test. +-const ignoredErrors = new Set(['EINVAL', 'EOVERFLOW']); +- +-tmpdir.refresh(); +-const filepath = path.resolve(tmpdir.path, 'timestamp'); +- +-await (await fsPromises.open(filepath, 'w')).close(); +- +-// Perform a trivial check to determine if filesystem supports setting +-// and retrieving atime and mtime. If it doesn't, skip the test. +-await fsPromises.utimes(filepath, 2, 2); +-const { atimeMs, mtimeMs } = await fsPromises.stat(filepath); +-if (atimeMs !== 2000 || mtimeMs !== 2000) { +- common.skip(`Unsupported filesystem (atime=${atimeMs}, mtime=${mtimeMs})`); +-} +- +-// Date might round down timestamp +-function closeEnough(actual, expected, margin) { +- // On ppc64, value is rounded to seconds +- if (process.arch === 'ppc64') { +- margin += 1000; +- } +- +- // Filesystems without support for timestamps before 1970-01-01, such as NFSv3, +- // should return 0 for negative numbers. Do not treat it as error. +- if (actual === 0 && expected < 0) { +- console.log(`ignored 0 while expecting ${expected}`); +- return; +- } +- +- assert.ok(Math.abs(Number(actual - expected)) < margin, +- `expected ${expected} ± ${margin}, got ${actual}`); +-} +- +-async function runTest(atime, mtime, margin = 0) { +- margin += Number.EPSILON; +- try { +- await fsPromises.utimes(filepath, new Date(atime), new Date(mtime)); +- } catch (e) { +- if (ignoredErrors.has(e.code)) return; +- throw e; +- } +- +- const stats = await fsPromises.stat(filepath); +- closeEnough(stats.atimeMs, atime, margin); +- closeEnough(stats.mtimeMs, mtime, margin); +- closeEnough(stats.atime.getTime(), new Date(atime).getTime(), margin); +- closeEnough(stats.mtime.getTime(), new Date(mtime).getTime(), margin); +- +- const statsBigint = await fsPromises.stat(filepath, { bigint: true }); +- closeEnough(statsBigint.atimeMs, BigInt(atime), margin); +- closeEnough(statsBigint.mtimeMs, BigInt(mtime), margin); +- closeEnough(statsBigint.atime.getTime(), new Date(atime).getTime(), margin); +- closeEnough(statsBigint.mtime.getTime(), new Date(mtime).getTime(), margin); +- +- const statsSync = fs.statSync(filepath); +- closeEnough(statsSync.atimeMs, atime, margin); +- closeEnough(statsSync.mtimeMs, mtime, margin); +- closeEnough(statsSync.atime.getTime(), new Date(atime).getTime(), margin); +- closeEnough(statsSync.mtime.getTime(), new Date(mtime).getTime(), margin); +- +- const statsSyncBigint = fs.statSync(filepath, { bigint: true }); +- closeEnough(statsSyncBigint.atimeMs, BigInt(atime), margin); +- closeEnough(statsSyncBigint.mtimeMs, BigInt(mtime), margin); +- closeEnough(statsSyncBigint.atime.getTime(), new Date(atime).getTime(), margin); +- closeEnough(statsSyncBigint.mtime.getTime(), new Date(mtime).getTime(), margin); +-} +- +-// Too high/low numbers produce too different results on different platforms +-{ +- // TODO(LiviaMedeiros): investigate outdated stat time on FreeBSD. +- // On Windows, filetime is stored and handled differently. Supporting dates +- // after Y2038 is preferred over supporting dates before 1970-01-01. +- if (!common.isFreeBSD && !common.isWindows) { +- await runTest(-40691, -355, 1); // Potential precision loss on 32bit +- await runTest(-355, -40691, 1); // Potential precision loss on 32bit +- await runTest(-1, -1); +- } +- await runTest(0, 0); +- await runTest(1, 1); +- await runTest(355, 40691, 1); // Precision loss on 32bit +- await runTest(40691, 355, 1); // Precision loss on 32bit +- await runTest(1713037251360, 1713037251360, 1); // Precision loss +-} -- cgit v1.2.3-60-g2f50