Commit f781f522 authored by Hannu Trey's avatar Hannu Trey Committed by Commit Bot

Re-detect the host time zone if requested by an embedder

Add an enum argument to DateTimeConfigurationChangeNotification to
control whether or not to redetect the host time zone. The default value
kSkip doesn't cause redetecting so that callers do not need to change if
they want the current behavior (e.g. Chromium).

Note that the host time zone detection does not work when v8 is run
inside a sandbox as in Chromium so that Chromium detects the host time
zone outside the sandbox before calling
DateTimeConfigurationChangeNotification. OTOH, other v8 embedders may
find it more convenient for v8 to do the host time zone detection on
their behalf. In that case, they can call the function with the new
argument set to value kRedetect.

Test:
With PHP+V8Js on linux, execute:
php -r '
  putenv("TZ=Europe/Helsinki");
  $v8 = new V8Js();
  $v8->executeString("print((new Date(0)).toString()+\"\\n\");");
  putenv("TZ=America/New_York");
  $v8->executeString("print((new Date(0)).toString()+\"\\n\");");'

Result before modification:
Thu Jan 01 1970 02:00:00 GMT+0200 (Eastern European Standard Time)
Thu Jan 01 1970 02:00:00 GMT+0200 (Eastern European Standard Time)

Result after modification:
Thu Jan 01 1970 02:00:00 GMT+0200 (Eastern European Standard Time)
Thu Jan 01 1970 02:00:00 GMT+0200 (Eastern European Standard Time)

Result after V8JS is modified to use value kRedetect when calling

Thu Jan 01 1970 02:00:00 GMT+0200 (Eastern European Standard Time)
Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time)

DateTimeConfigurationChangeNotification: 
Change-Id: I005192dd42669a94f606a49baa9eafad3475b9fd
Reviewed-on: https://chromium-review.googlesource.com/c/1449637Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJungshik Shin <jshin@chromium.org>
Commit-Queue: Jungshik Shin <jshin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59613}
parent e15586e7
......@@ -84,6 +84,7 @@ Geoffrey Garside <ggarside@gmail.com>
Gergely Nagy <ngg@ngg.hu>
Gus Caplan <me@gus.host>
Gwang Yoon Hwang <ryumiel@company100.net>
Hannu Trey <hannu.trey@gmail.com>
Henrique Ferreiro <henrique.ferreiro@gmail.com>
Hirofumi Mako <mkhrfm@gmail.com>
Honggyu Kim <honggyu.kp@gmail.com>
......
......@@ -5288,6 +5288,21 @@ class V8_EXPORT Date : public Object {
V8_INLINE static Date* Cast(Value* obj);
/**
* Time zone redetection indicator for
* DateTimeConfigurationChangeNotification.
*
* kSkip indicates V8 that the notification should not trigger redetecting
* host time zone. kRedetect indicates V8 that host time zone should be
* redetected, and used to set the default time zone.
*
* The host time zone detection may require file system access or similar
* operations unlikely to be available inside a sandbox. If v8 is run inside a
* sandbox, the host time zone has to be detected outside the sandbox before
* calling DateTimeConfigurationChangeNotification function.
*/
enum class TimeZoneDetection { kSkip, kRedetect };
/**
* Notification that the embedder has changed the time zone,
* daylight savings time, or other date / time configuration
......@@ -5300,7 +5315,9 @@ class V8_EXPORT Date : public Object {
* This API should not be called more than needed as it will
* negatively impact the performance of date operations.
*/
static void DateTimeConfigurationChangeNotification(Isolate* isolate);
static void DateTimeConfigurationChangeNotification(
Isolate* isolate,
TimeZoneDetection time_zone_detection = TimeZoneDetection::kSkip);
private:
static void CheckCast(Value* obj);
......
......@@ -6761,12 +6761,23 @@ double v8::Date::ValueOf() const {
return jsdate->value()->Number();
}
void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
// Assert that the static TimeZoneDetection cast in
// DateTimeConfigurationChangeNotification is valid.
#define TIME_ZONE_DETECTION_ASSERT_EQ(value) \
STATIC_ASSERT( \
static_cast<int>(v8::Date::TimeZoneDetection::value) == \
static_cast<int>(base::TimezoneCache::TimeZoneDetection::value))
TIME_ZONE_DETECTION_ASSERT_EQ(kSkip);
TIME_ZONE_DETECTION_ASSERT_EQ(kRedetect);
#undef TIME_ZONE_DETECTION_ASSERT_EQ
void v8::Date::DateTimeConfigurationChangeNotification(
Isolate* isolate, TimeZoneDetection time_zone_detection) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, Date, DateTimeConfigurationChangeNotification);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
i_isolate->date_cache()->ResetDateCache();
i_isolate->date_cache()->ResetDateCache(
static_cast<base::TimezoneCache::TimeZoneDetection>(time_zone_detection));
#ifdef V8_INTL_SUPPORT
i_isolate->clear_cached_icu_object(
i::Isolate::ICUObjectCacheType::kDefaultSimpleDateFormat);
......@@ -6777,7 +6788,6 @@ void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
#endif // V8_INTL_SUPPORT
}
MaybeLocal<v8::RegExp> v8::RegExp::New(Local<Context> context,
Local<String> pattern, Flags flags) {
PREPARE_FOR_EXECUTION(context, RegExp, New, RegExp);
......
......@@ -14,7 +14,7 @@ namespace base {
class PosixTimezoneCache : public TimezoneCache {
public:
double DaylightSavingsOffset(double time_ms) override;
void Clear() override {}
void Clear(TimeZoneDetection) override {}
~PosixTimezoneCache() override = default;
protected:
......
......@@ -113,7 +113,7 @@ class WindowsTimezoneCache : public TimezoneCache {
~WindowsTimezoneCache() override {}
void Clear() override { initialized_ = false; }
void Clear(TimeZoneDetection) override { initialized_ = false; }
const char* LocalTimezone(double time) override;
......
......@@ -23,8 +23,22 @@ class TimezoneCache {
// https://github.com/tc39/ecma262/pull/778
virtual double LocalTimeOffset(double time_ms, bool is_utc) = 0;
/**
* Time zone redetection indicator for Clear function.
*
* kSkip indicates host time zone doesn't have to be redetected.
* kRedetect indicates host time zone should be redetected, and used to set
* the default time zone.
*
* The host time zone detection may require file system access or similar
* operations unlikely to be available inside a sandbox. If v8 is run inside a
* sandbox, the host time zone has to be detected outside the sandbox
* separately.
*/
enum class TimeZoneDetection { kSkip, kRedetect };
// Called when the local timezone changes
virtual void Clear() = 0;
virtual void Clear(TimeZoneDetection time_zone_detection) = 0;
// Called when tearing down the isolate
virtual ~TimezoneCache() = default;
......
......@@ -34,10 +34,11 @@ DateCache::DateCache()
base::OS::CreateTimezoneCache()
#endif
) {
ResetDateCache();
ResetDateCache(base::TimezoneCache::TimeZoneDetection::kSkip);
}
void DateCache::ResetDateCache() {
void DateCache::ResetDateCache(
base::TimezoneCache::TimeZoneDetection time_zone_detection) {
if (stamp_->value() >= Smi::kMaxValue) {
stamp_ = Smi::zero();
} else {
......@@ -58,7 +59,7 @@ void DateCache::ResetDateCache() {
#ifdef V8_INTL_SUPPORT
}
#endif
tz_cache_->Clear();
tz_cache_->Clear(time_zone_detection);
tz_name_ = nullptr;
dst_tz_name_ = nullptr;
}
......
......@@ -45,10 +45,9 @@ class DateCache {
tz_cache_ = nullptr;
}
// Clears cached timezone information and increments the cache stamp.
void ResetDateCache();
void ResetDateCache(
base::TimezoneCache::TimeZoneDetection time_zone_detection);
// Computes floor(time_ms / kMsPerDay).
static int DaysFromTime(int64_t time_ms) {
......
......@@ -1728,9 +1728,9 @@ MaybeHandle<String> Intl::Normalize(Isolate* isolate, Handle<String> string,
// functionality in a straightforward way.
class ICUTimezoneCache : public base::TimezoneCache {
public:
ICUTimezoneCache() : timezone_(nullptr) { Clear(); }
ICUTimezoneCache() : timezone_(nullptr) { Clear(TimeZoneDetection::kSkip); }
~ICUTimezoneCache() override { Clear(); }
~ICUTimezoneCache() override { Clear(TimeZoneDetection::kSkip); }
const char* LocalTimezone(double time_ms) override;
......@@ -1738,7 +1738,7 @@ class ICUTimezoneCache : public base::TimezoneCache {
double LocalTimeOffset(double time_ms, bool is_utc) override;
void Clear() override;
void Clear(TimeZoneDetection time_zone_detection) override;
private:
icu::TimeZone* GetTimeZone();
......@@ -1811,11 +1811,14 @@ double ICUTimezoneCache::LocalTimeOffset(double time_ms, bool is_utc) {
return raw_offset + dst_offset;
}
void ICUTimezoneCache::Clear() {
void ICUTimezoneCache::Clear(TimeZoneDetection time_zone_detection) {
delete timezone_;
timezone_ = nullptr;
timezone_name_.clear();
dst_timezone_name_.clear();
if (time_zone_detection == TimeZoneDetection::kRedetect) {
icu::TimeZone::adoptDefault(icu::TimeZone::detectHostTimeZone());
}
}
base::TimezoneCache* Intl::CreateTimeZoneCache() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment