From 5c64146beadb33f5f030c5880a1f75a9ab994a93 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Tue, 28 Jan 2025 18:13:41 +0530 Subject: [PATCH] fix(ext/node): clear tz cache when setting process.env.TZ (#27826) --- ext/os/lib.rs | 28 ++++++++++ tests/node_compat/config.jsonc | 1 + tests/node_compat/runner/TODO.md | 3 +- .../test/parallel/test-process-env-tz.js | 54 +++++++++++++++++++ tests/specs/run/tz_env/__test__.jsonc | 9 ++++ tests/specs/run/tz_env/main.ts | 13 +++++ 6 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 tests/node_compat/test/parallel/test-process-env-tz.js create mode 100644 tests/specs/run/tz_env/__test__.jsonc create mode 100644 tests/specs/run/tz_env/main.ts diff --git a/ext/os/lib.rs b/ext/os/lib.rs index a2d5a7193b88b4..337906c2ac7e5e 100644 --- a/ext/os/lib.rs +++ b/ext/os/lib.rs @@ -166,9 +166,35 @@ fn op_exec_path(state: &mut OpState) -> Result { .map_err(OsError::InvalidUtf8) } +fn dt_change_notif(isolate: &mut v8::Isolate, key: &str) { + extern "C" { + #[cfg(unix)] + fn tzset(); + + #[cfg(windows)] + fn _tzset(); + } + + if key == "TZ" { + // SAFETY: tzset/_tzset (libc) is called to update the timezone information + unsafe { + #[cfg(unix)] + tzset(); + + #[cfg(windows)] + _tzset(); + } + + isolate.date_time_configuration_change_notification( + v8::TimeZoneDetection::Redetect, + ); + } +} + #[op2(fast, stack_trace)] fn op_set_env( state: &mut OpState, + scope: &mut v8::HandleScope, #[string] key: &str, #[string] value: &str, ) -> Result<(), OsError> { @@ -182,7 +208,9 @@ fn op_set_env( if value.contains('\0') { return Err(OsError::EnvInvalidValue(value.to_string())); } + env::set_var(key, value); + dt_change_notif(scope, key); Ok(()) } diff --git a/tests/node_compat/config.jsonc b/tests/node_compat/config.jsonc index 4d77a290dd9a59..51ee6db3d9c77b 100644 --- a/tests/node_compat/config.jsonc +++ b/tests/node_compat/config.jsonc @@ -854,6 +854,7 @@ "test-process-emitwarning.js", "test-process-env-allowed-flags.js", "test-process-env-delete.js", + "test-process-env-tz.js", "test-process-env-windows-error-reset.js", "test-process-exit-from-before-exit.js", "test-process-exit-handler.js", diff --git a/tests/node_compat/runner/TODO.md b/tests/node_compat/runner/TODO.md index c2e360aef59ddb..06c4cd800664cc 100644 --- a/tests/node_compat/runner/TODO.md +++ b/tests/node_compat/runner/TODO.md @@ -1,7 +1,7 @@ # Remaining Node Tests -1154 tests out of 3681 have been ported from Node 20.11.1 (31.35% ported, 69.19% remaining). +1155 tests out of 3681 have been ported from Node 20.11.1 (31.38% ported, 69.17% remaining). NOTE: This file should not be manually edited. Please edit `tests/node_compat/config.json` and run `deno task setup` in `tests/node_compat/runner` dir instead. @@ -1578,7 +1578,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co - [parallel/test-process-env-ignore-getter-setter.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-env-ignore-getter-setter.js) - [parallel/test-process-env-sideeffects.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-env-sideeffects.js) - [parallel/test-process-env-symbols.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-env-symbols.js) -- [parallel/test-process-env-tz.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-env-tz.js) - [parallel/test-process-env.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-env.js) - [parallel/test-process-euid-egid.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-euid-egid.js) - [parallel/test-process-exception-capture-errors.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-process-exception-capture-errors.js) diff --git a/tests/node_compat/test/parallel/test-process-env-tz.js b/tests/node_compat/test/parallel/test-process-env-tz.js new file mode 100644 index 00000000000000..ea28309f45a491 --- /dev/null +++ b/tests/node_compat/test/parallel/test-process-env-tz.js @@ -0,0 +1,54 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 20.11.1 +// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually. + +'use strict'; +const common = require('../common'); +const assert = require('assert'); + +if (!common.isMainThread) + common.skip('process.env.TZ is not intercepted in Workers'); + +if (common.isWindows) // Using a different TZ format. + common.skip('todo: test on Windows'); + +const date = new Date('2018-04-14T12:34:56.789Z'); + +process.env.TZ = 'Europe/Amsterdam'; + +if (date.toString().includes('(Europe)')) + common.skip('not using bundled ICU'); // Shared library or --with-intl=none. + +if ('Sat Apr 14 2018 12:34:56 GMT+0000 (GMT)' === date.toString()) + common.skip('missing tzdata'); // Alpine buildbots lack Europe/Amsterdam. + +if (date.toString().includes('(Central European Time)') || + date.toString().includes('(CET)')) { + // The AIX and SmartOS buildbots report 2018 CEST as CET + // because apparently for them that's still the deep future. + common.skip('tzdata too old'); +} + +// Text representation of timezone depends on locale in environment +assert.match( + date.toString(), + /^Sat Apr 14 2018 14:34:56 GMT\+0200 \(.+\)$/); + +process.env.TZ = 'Europe/London'; +assert.match( + date.toString(), + /^Sat Apr 14 2018 13:34:56 GMT\+0100 \(.+\)$/); + +process.env.TZ = 'Etc/UTC'; +assert.match( + date.toString(), + /^Sat Apr 14 2018 12:34:56 GMT\+0000 \(.+\)$/); + +// Just check that deleting the environment variable doesn't crash the process. +// We can't really check the result of date.toString() because we don't know +// the default time zone. +delete process.env.TZ; +date.toString(); diff --git a/tests/specs/run/tz_env/__test__.jsonc b/tests/specs/run/tz_env/__test__.jsonc new file mode 100644 index 00000000000000..5a3aede3926704 --- /dev/null +++ b/tests/specs/run/tz_env/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "steps": [ + { + "if": "unix", + "args": "run -A main.ts", + "output": "ok\n" + } + ] +} diff --git a/tests/specs/run/tz_env/main.ts b/tests/specs/run/tz_env/main.ts new file mode 100644 index 00000000000000..61bf4363c496a8 --- /dev/null +++ b/tests/specs/run/tz_env/main.ts @@ -0,0 +1,13 @@ +const date = new Date("2018-04-14T12:34:56.789Z"); + +Deno.env.set("TZ", "Europe/Amsterdam"); +if (!date.toString().match(/^Sat Apr 14 2018 14:34:56 GMT\+0200 \(.+\)$/)) { + throw new Error(`date.toString() did not match the expected pattern`); +} + +Deno.env.set("TZ", "Europe/London"); +if (!date.toString().match(/^Sat Apr 14 2018 13:34:56 GMT\+0100 \(.+\)$/)) { + throw new Error(`date.toString() did not match the expected pattern`); +} + +console.log("ok");