| // Copyright 2025 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/objects/js-temporal-zoneinfo64.h" |
| |
| #include <iostream> |
| |
| #include "src/base/logging.h" |
| #include "temporal_rs/Provider.hpp" |
| #include "temporal_rs/TimeZone.hpp" |
| |
| #ifdef V8_INTL_SUPPORT |
| #include "udatamem.h" |
| #else |
| // Defined in builtins-temporal-zoneinfo64-data.cc, generated by |
| // include-file-as-bytes.py |
| extern "C" uint32_t zoneinfo64_static_data[]; |
| extern "C" size_t zoneinfo64_static_data_len; |
| #endif |
| |
| namespace v8::internal { |
| |
| ZoneInfo64Provider::ZoneInfo64Provider() { |
| #ifdef V8_INTL_SUPPORT |
| UErrorCode status = U_ZERO_ERROR; |
| memory = udata_open(0, "res", "zoneinfo64", &status); |
| if (U_FAILURE(status)) { |
| DCHECK_WITH_MSG(false, "Failed to open zoneinfo64.res"); |
| provider = temporal_rs::Provider::empty(); |
| return; |
| } |
| // NOT udata_getLength: this ignores the header, |
| // and we're parsing resb files with the header |
| auto length = memory->length; |
| const void* data = udata_getRawMemory(memory); |
| DCHECK_WITH_MSG(length % 4 == 0, "ICU4C should align udata to uint32_t"); |
| if (length % 4 != 0) { |
| // This really shouldn't happen: ICU4C aligns these files |
| // to 4 when baking them in |
| provider = temporal_rs::Provider::empty(); |
| return; |
| } |
| |
| const uint32_t* data_32 = static_cast<const uint32_t*>(data); |
| std::span<const uint32_t> data_span(data_32, length / 4); |
| |
| #else |
| std::span<const uint32_t> data_span(zoneinfo64_static_data, |
| zoneinfo64_static_data_len); |
| #endif |
| |
| auto result = temporal_rs::Provider::new_zoneinfo64(data_span); |
| DCHECK_WITH_MSG(result.is_ok(), "Baked-in zoneinfo64 file must parse"); |
| if (result.is_ok()) { |
| provider = std::move(result).ok().value(); |
| } else { |
| provider = temporal_rs::Provider::empty(); |
| } |
| } |
| |
| ZoneInfo64Provider& ZoneInfo64Provider::Singleton() { |
| // Allocate it so that it gets leaked (-Wno-exit-destructors) |
| static ZoneInfo64Provider* SINGLETON = new ZoneInfo64Provider(); |
| return *SINGLETON; |
| } |
| |
| // This destructor exists for completeness in case someone decides to use this |
| // as a stack value, though the default way of accessing this is via singleton. |
| ZoneInfo64Provider::~ZoneInfo64Provider() { |
| // Release provider first since it |
| // may reference memory |
| provider = nullptr; |
| |
| // Then clean up memory |
| // This ideally is a no-op when using static data |
| #ifdef V8_INTL_SUPPORT |
| if (memory) { |
| udata_close(memory); |
| } |
| #endif |
| } |
| |
| } // namespace v8::internal |