mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Update timezone and locale codes
* Use ICU function for reading default system timezone * Update default locale reading logic(remove POSIX postfix & ignore 'C' locale) * Refactor global timezone, vzone, tzname codes Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
80fea01dd1
commit
7a98a9ba52
11 changed files with 158 additions and 34 deletions
7
.github/workflows/es-actions.yml
vendored
7
.github/workflows/es-actions.yml
vendored
|
|
@ -64,6 +64,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
arch: [x86, x86_64]
|
||||
api: [28]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
|
@ -86,12 +87,12 @@ jobs:
|
|||
path: |
|
||||
~/.android/avd/*
|
||||
~/.android/adb*
|
||||
key: avd-29-${{ matrix.arch }}
|
||||
key: avd-${{ matrix.api }}-${{ matrix.arch }}
|
||||
- name: Create AVD and generate snapshot for caching
|
||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: 29
|
||||
api-level: ${{ matrix.api }}
|
||||
arch: ${{ matrix.arch }}
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
|
|
@ -100,7 +101,7 @@ jobs:
|
|||
- name: Run tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: 29
|
||||
api-level: ${{ matrix.api }}
|
||||
arch: ${{ matrix.arch }}
|
||||
force-avd-creation: false
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.EscargotAndroidTestShell"
|
||||
tools:targetApi="31">
|
||||
<profileable android:shell="true" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ static Value temporalInstantFromEpoch(ExecutionState& state, size_t argc, Value*
|
|||
|
||||
static Value builtinTemporalNowTimeZone(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
|
||||
{
|
||||
state.context()->vmInstance()->ensureTimezone();
|
||||
return Value(String::fromUTF8(state.context()->vmInstance()->timezoneID().c_str(), state.context()->vmInstance()->timezoneID().length(), true));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,9 +182,6 @@ static void toDateTimeOptionsTest(ExecutionState& state, Value options, AtomicSt
|
|||
|
||||
static String* defaultTimeZone(ExecutionState& state)
|
||||
{
|
||||
#if !defined(OS_WINDOWS_UWP)
|
||||
state.context()->vmInstance()->ensureTimezone();
|
||||
#endif
|
||||
return String::fromUTF8(state.context()->vmInstance()->timezoneID().data(), state.context()->vmInstance()->timezoneID().length());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ time64_t DateObject::applyLocalTimezoneOffset(ExecutionState& state, time64_t t)
|
|||
|
||||
// roughly check range before calling yearFromTime function
|
||||
#if defined(ENABLE_ICU) && !defined(OS_WINDOWS_UWP)
|
||||
stdOffset = vzone_getRawOffset(state.context()->vmInstance()->timezone());
|
||||
stdOffset = vzone_getRawOffset(state.context()->vmInstance()->vzone());
|
||||
#else
|
||||
stdOffset = 0;
|
||||
#endif
|
||||
|
|
@ -301,7 +301,7 @@ time64_t DateObject::applyLocalTimezoneOffset(ExecutionState& state, time64_t t)
|
|||
|
||||
t += msBetweenYears;
|
||||
#if defined(ENABLE_ICU) && !defined(OS_WINDOWS_UWP)
|
||||
vzone_getOffset3(state.context()->vmInstance()->timezone(), t, true, stdOffset, dstOffset, succ);
|
||||
vzone_getOffset3(state.context()->vmInstance()->vzone(), t, true, stdOffset, dstOffset, succ);
|
||||
#else
|
||||
dstOffset = 0;
|
||||
#endif
|
||||
|
|
@ -1243,7 +1243,7 @@ void DateObject::resolveCache(ExecutionState& state)
|
|||
int32_t stdOffset = 0, dstOffset = 0;
|
||||
#if defined(ENABLE_ICU) && !defined(OS_WINDOWS_UWP)
|
||||
UErrorCode succ = U_ZERO_ERROR;
|
||||
vzone_getOffset3(state.context()->vmInstance()->timezone(), t, true, stdOffset, dstOffset, succ);
|
||||
vzone_getOffset3(state.context()->vmInstance()->vzone(), t, true, stdOffset, dstOffset, succ);
|
||||
#endif
|
||||
|
||||
m_cachedLocal.isdst = dstOffset == 0 ? 0 : 1;
|
||||
|
|
@ -1300,24 +1300,23 @@ String* DateObject::toTimeString(ExecutionState& state)
|
|||
{
|
||||
RESOLVECACHE(state);
|
||||
if (IS_VALID_TIME(m_primitiveValue)) {
|
||||
char buffer[32];
|
||||
char buffer[256];
|
||||
int tzOffsetAsMin = -getTimezoneOffset(state); // 540
|
||||
int tzOffsetHour = (tzOffsetAsMin / const_Date_minutesPerHour);
|
||||
int tzOffsetMin = ((tzOffsetAsMin / (double)const_Date_minutesPerHour) - tzOffsetHour) * 60;
|
||||
tzOffsetHour *= 100;
|
||||
const std::string& timeZoneName = state.context()->vmInstance()->tzname(m_cachedLocal.isdst ? 1 : 0);
|
||||
#if defined(OS_WINDOWS)
|
||||
const char* timeZoneName = _tzname[m_cachedLocal.isdst ? 1 : 0];
|
||||
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%s%04d", getHours(state), getMinutes(state), getSeconds(state), (tzOffsetAsMin < 0) ? "-" : "+", std::abs(tzOffsetHour + tzOffsetMin));
|
||||
StringBuilder sb;
|
||||
sb.appendString(buffer);
|
||||
sb.appendChar('(');
|
||||
sb.appendString(String::fromUTF8(timeZoneName, strlen(timeZoneName)));
|
||||
sb.appendString(String::fromUTF8(timeZoneName.data(), timeZoneName.length()));
|
||||
sb.appendChar(')');
|
||||
return sb.finalize();
|
||||
#else
|
||||
const char* timeZoneName = m_cachedLocal.isdst ? tzname[1] : tzname[0];
|
||||
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%s%04d (%s)", getHours(state), getMinutes(state), getSeconds(state), (tzOffsetAsMin < 0) ? "-" : "+", std::abs(tzOffsetHour + tzOffsetMin), timeZoneName);
|
||||
return new ASCIIString(buffer);
|
||||
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%s%04d (%s)", getHours(state), getMinutes(state), getSeconds(state), (tzOffsetAsMin < 0) ? "-" : "+", std::abs(tzOffsetHour + tzOffsetMin), timeZoneName.data());
|
||||
return String::fromUTF8(buffer, strnlen(buffer, sizeof(buffer)));
|
||||
#endif
|
||||
} else {
|
||||
return new ASCIIString(invalidDate);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ NT_TIB* getTIB()
|
|||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <time.h> // for tzname
|
||||
|
||||
namespace Escargot {
|
||||
|
||||
#if defined(ENABLE_WASM)
|
||||
|
|
@ -436,8 +438,14 @@ VMInstance::VMInstance(const char* locale, const char* timezone, const char* bas
|
|||
m_locale = uloc_getDefault();
|
||||
#endif
|
||||
}
|
||||
|
||||
// remove posix postfix(A_POSIX -> A)
|
||||
if (m_locale.find("_POSIX") == m_locale.length() - 6) {
|
||||
m_locale = m_locale.substr(0, m_locale.length() - 6);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// add gc event callback
|
||||
GCEventListenerSet& list = ThreadLocal::gcEventListenerSet();
|
||||
list.ensureMarkStartListeners()->push_back(std::make_pair(vmMarkStartCallback, this));
|
||||
|
|
@ -566,19 +574,89 @@ static std::string findTimezone()
|
|||
#endif
|
||||
|
||||
|
||||
void VMInstance::ensureTimezone()
|
||||
void VMInstance::ensureVZone()
|
||||
{
|
||||
ensureTimezoneID();
|
||||
|
||||
#if !defined(OS_WINDOWS_UWP)
|
||||
auto u16 = utf8StringToUTF16String(timezoneID().data(), timezoneID().size());
|
||||
m_timezone = vzone_openID(u16.data(), u16.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
void VMInstance::ensureTimezoneID()
|
||||
{
|
||||
if (m_timezoneID == "") {
|
||||
m_timezoneID = findTimezone();
|
||||
} else {
|
||||
#if !defined(OS_WINDOWS_UWP)
|
||||
tzset();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void VMInstance::ensureTzname()
|
||||
{
|
||||
if (m_tzname[0].size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(OS_WINDOWS_UWP)
|
||||
auto u16 = utf8StringToUTF16String(m_timezoneID.data(), m_timezoneID.size());
|
||||
m_timezone = vzone_openID(u16.data(), u16.size());
|
||||
auto u16timezoneID = String::fromUTF8(timezoneID().data(), timezoneID().size())->toUTF16StringData();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UCalendar* cal = ucal_open(u16timezoneID.data(), u16timezoneID.length(), "en", UCAL_DEFAULT, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
UChar name[128];
|
||||
int32_t nameLength = ucal_getTimeZoneDisplayName(cal, UCalendarDisplayNameType::UCAL_STANDARD, locale().data(), name, sizeof(name) / sizeof(UChar), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
m_tzname[0] = (new UTF16String(name, nameLength))->toNonGCUTF8StringData();
|
||||
nameLength = ucal_getTimeZoneDisplayName(cal, UCalendarDisplayNameType::UCAL_DST, locale().data(), name, sizeof(name) / sizeof(UChar), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
m_tzname[1] = (new UTF16String(name, nameLength))->toNonGCUTF8StringData();
|
||||
}
|
||||
}
|
||||
ucal_close(cal);
|
||||
if (m_tzname[0].size() && m_tzname[1].size()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback route
|
||||
#if defined(OS_WINDOWS)
|
||||
size_t s;
|
||||
char tznameResult[100];
|
||||
_get_tzname(&s, tznameResult, sizeof(tznameResult), 0);
|
||||
m_tzname[0] = tznameResult;
|
||||
_get_tzname(&s, tznameResult, sizeof(tznameResult), 1);
|
||||
m_tzname[1] = tznameResult;
|
||||
#else
|
||||
// FIXME tzset function is MT-safe but changing TZ value and read tzname is not MT-safe
|
||||
#if defined(ENABLE_THREADING)
|
||||
static std::mutex s_mutex;
|
||||
std::lock_guard<std::mutex> guard(s_mutex);
|
||||
#endif
|
||||
char* oldTZ = getenv("TZ");
|
||||
setenv("TZ", timezoneID().data(), 1);
|
||||
tzset();
|
||||
m_tzname[0] = ::tzname[0];
|
||||
m_tzname[1] = ::tzname[1];
|
||||
if (oldTZ) {
|
||||
setenv("TZ", oldTZ, 1);
|
||||
} else {
|
||||
unsetenv("TZ");
|
||||
}
|
||||
tzset();
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
void VMInstance::ensureTzname()
|
||||
{
|
||||
if (m_tzname[0].size()) {
|
||||
return;
|
||||
}
|
||||
tzset();
|
||||
#if defined(OS_WINDOWS)
|
||||
m_tzname[0] = ::_tzname[0];
|
||||
m_tzname[1] = ::_tzname[1];
|
||||
#else
|
||||
m_tzname[0] = ::tzname[0];
|
||||
m_tzname[1] = ::tzname[1];
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -123,24 +123,29 @@ public:
|
|||
return m_locale;
|
||||
}
|
||||
|
||||
const std::string& timezoneID()
|
||||
{
|
||||
return m_timezoneID;
|
||||
}
|
||||
|
||||
void ensureTimezone();
|
||||
|
||||
#if !defined(OS_WINDOWS_UWP)
|
||||
VZone* timezone()
|
||||
VZone* vzone()
|
||||
{
|
||||
if (m_timezone == nullptr) {
|
||||
ensureTimezone();
|
||||
ensureVZone();
|
||||
}
|
||||
return m_timezone;
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string& timezoneID()
|
||||
{
|
||||
ensureTimezoneID();
|
||||
return m_timezoneID;
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string& tzname(size_t i)
|
||||
{
|
||||
ensureTzname();
|
||||
return m_tzname[i];
|
||||
}
|
||||
|
||||
DateObject* cachedUTC(ExecutionState& state);
|
||||
|
||||
// object
|
||||
|
|
@ -461,7 +466,11 @@ private:
|
|||
VZone* m_timezone;
|
||||
#endif
|
||||
std::string m_timezoneID;
|
||||
void ensureTimezoneID();
|
||||
void ensureVZone();
|
||||
#endif
|
||||
void ensureTzname();
|
||||
std::string m_tzname[2];
|
||||
DateObject* m_cachedUTC;
|
||||
|
||||
// promise job queue
|
||||
|
|
|
|||
4
third_party/runtime_icu_binder/ICUPolyfill.h
vendored
4
third_party/runtime_icu_binder/ICUPolyfill.h
vendored
|
|
@ -114,6 +114,8 @@
|
|||
|
||||
#define ucal_open RuntimeICUBinder::ICU::instance().ucal_open
|
||||
#define ucal_close RuntimeICUBinder::ICU::instance().ucal_close
|
||||
#define ucal_getDefaultTimeZone RuntimeICUBinder::ICU::instance().ucal_getDefaultTimeZone
|
||||
#define ucal_getTimeZoneDisplayName RuntimeICUBinder::ICU::instance().ucal_getTimeZoneDisplayName
|
||||
#define ucal_getKeywordValuesForLocale RuntimeICUBinder::ICU::instance().ucal_getKeywordValuesForLocale
|
||||
#define ucal_openTimeZoneIDEnumeration RuntimeICUBinder::ICU::instance().ucal_openTimeZoneIDEnumeration
|
||||
#define ucal_openTimeZones RuntimeICUBinder::ICU::instance().ucal_openTimeZones
|
||||
|
|
@ -181,6 +183,8 @@
|
|||
#define ures_getNextResource RuntimeICUBinder::ICU::instance().ures_getNextResource
|
||||
#define ures_hasNext RuntimeICUBinder::ICU::instance().ures_hasNext
|
||||
#define ures_resetIterator RuntimeICUBinder::ICU::instance().ures_resetIterator
|
||||
#define ures_getSize RuntimeICUBinder::ICU::instance().ures_getSize
|
||||
#define ures_getStringByIndex RuntimeICUBinder::ICU::instance().ures_getStringByIndex
|
||||
|
||||
#define unumf_openForSkeletonAndLocale RuntimeICUBinder::ICU::instance().unumf_openForSkeletonAndLocale
|
||||
#define unumf_openForSkeletonAndLocaleWithError RuntimeICUBinder::ICU::instance().unumf_openForSkeletonAndLocaleWithError
|
||||
|
|
|
|||
18
third_party/runtime_icu_binder/ICUTypes.h
vendored
18
third_party/runtime_icu_binder/ICUTypes.h
vendored
|
|
@ -5781,6 +5781,24 @@ enum UCalendarDateFields {
|
|||
UCAL_DAY_OF_MONTH = UCAL_DATE
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible formats for a UCalendar's display name
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
enum UCalendarDisplayNameType {
|
||||
/** Standard display name */
|
||||
UCAL_STANDARD,
|
||||
/** Short standard display name */
|
||||
UCAL_SHORT_STANDARD,
|
||||
/** Daylight savings display name */
|
||||
UCAL_DST,
|
||||
/** Short daylight savings display name */
|
||||
UCAL_SHORT_DST
|
||||
};
|
||||
|
||||
/** @stable ICU 2.0 */
|
||||
typedef enum UCalendarDisplayNameType UCalendarDisplayNameType;
|
||||
|
||||
/** @stable ICU 2.0 */
|
||||
typedef enum UCalendarDateFields UCalendarDateFields;
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -242,7 +242,10 @@ std::string ICU::findSystemLocale()
|
|||
}
|
||||
c = setlocale(LC_CTYPE, "");
|
||||
if (c && strlen(c)) {
|
||||
return extractLocaleName(c);
|
||||
auto locale = extractLocaleName(c);
|
||||
if (locale != "C") {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
return ICU::instance().uloc_getDefault();
|
||||
}
|
||||
|
|
@ -304,8 +307,19 @@ std::string ICU::findSystemTimezoneName()
|
|||
} else if (timeValueFromFile("/etc/TIMEZONE", "TZ", tz, tzSize)) { // Solaris.
|
||||
return tz;
|
||||
}
|
||||
|
||||
#endif
|
||||
UChar result[256];
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t len = ICU::instance().ucal_getDefaultTimeZone(result, sizeof(result) / sizeof(UChar), &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
std::string u8Result;
|
||||
for (int32_t i = 0; i < len; i ++) {
|
||||
u8Result.push_back(result[i]);
|
||||
}
|
||||
return u8Result;
|
||||
}
|
||||
|
||||
// fallback
|
||||
time_t t;
|
||||
tm lt;
|
||||
t = time(NULL);
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@ namespace RuntimeICUBinder {
|
|||
F(unumsys_getName, const char* (*)(const UNumberingSystem* unumsys), const char*) \
|
||||
F(unumsys_open, UNumberingSystem* (*)(const char* locale, UErrorCode* status), UNumberingSystem*) \
|
||||
F(ucal_open, UCalendar* (*)(const UChar* zoneID, int32_t len, const char* locale, UCalendarType type, UErrorCode* status), UCalendar*) \
|
||||
F(ucal_getDefaultTimeZone, int32_t (*)(UChar* result, int32_t resultCapacity, UErrorCode* ec), int32_t) \
|
||||
F(ucal_getTimeZoneDisplayName, int32_t (*)(const UCalendar* cal, UCalendarDisplayNameType type, const char* locale, UChar* result, int32_t resultLength, UErrorCode* status), int32_t) \
|
||||
F(ucal_getKeywordValuesForLocale, UEnumeration* (*)(const char* key, const char* locale, UBool commonlyUsed, UErrorCode* status), UEnumeration*) \
|
||||
F(ucal_openTimeZoneIDEnumeration, UEnumeration* (*)(USystemTimeZoneType zoneType, const char* region, const int32_t* rawOffset, UErrorCode* ec), UEnumeration*) \
|
||||
F(ucal_openTimeZones, UEnumeration* (*)(UErrorCode * ec), UEnumeration*) \
|
||||
|
|
@ -156,6 +158,8 @@ namespace RuntimeICUBinder {
|
|||
F(ures_getKey, const char* (*)(const UResourceBundle* resourceBundle), const char*) \
|
||||
F(ures_getNextResource, UResourceBundle* (*)(UResourceBundle * resourceBundle, UResourceBundle * fillIn, UErrorCode * status), UResourceBundle*) \
|
||||
F(ures_hasNext, UBool (*)(const UResourceBundle* resourceBundle), UBool) \
|
||||
F(ures_getSize, int32_t (*)(const UResourceBundle* resourceBundle), int32_t) \
|
||||
F(ures_getStringByIndex, const UChar* (*)(const UResourceBundle *resourceBundle, int32_t indexS, int32_t* len, UErrorCode *status), const UChar*) \
|
||||
F(uplrules_select, int32_t (*)(const UPluralRules* uplrules, double number, UChar* keyword, int32_t capacity, UErrorCode* status), int32_t) \
|
||||
F(uplrules_getKeywords, UEnumeration* (*)(const UPluralRules* uplrules, UErrorCode* status), UEnumeration*) \
|
||||
F(uplrules_open, UPluralRules* (*)(const char* locale, UErrorCode* status), UPluralRules*) \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue