Implement Intl.DurationFormat, Intl.DurationFormat.supportedLocalesOf and Intl.DurationFormat.prototype.format

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2025-07-30 12:30:45 +09:00 committed by MuHong Byun
commit 54b0cf8f65
15 changed files with 1442 additions and 90 deletions

View file

@ -94,12 +94,11 @@ IF (ESCARGOT_LIBICU_SUPPORT)
IF (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_ICU -DENABLE_INTL -DENABLE_RUNTIME_ICU_BINDER)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_DISPLAYNAMES -DENABLE_INTL_NUMBERFORMAT -DENABLE_INTL_PLURALRULES)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_RELATIVETIMEFORMAT -DENABLE_INTL_LISTFORMAT)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_RELATIVETIMEFORMAT -DENABLE_INTL_LISTFORMAT -DENABLE_INTL_DURATIONFORMAT)
ELSE()
IF (NOT ${ESCARGOT_HOST} STREQUAL "windows")
# windows icu cannot support these feature yet.(~10.0.18362)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_DISPLAYNAMES -DENABLE_INTL_NUMBERFORMAT -DENABLE_INTL_PLURALRULES)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_RELATIVETIMEFORMAT -DENABLE_INTL_LISTFORMAT)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_INTL_RELATIVETIMEFORMAT -DENABLE_INTL_LISTFORMAT -DENABLE_INTL_DURATIONFORMAT)
PKG_CHECK_MODULES(ICU REQUIRED icu-uc icu-i18n)
ENDIF()

View file

@ -60,6 +60,7 @@
#include "intl/IntlRelativeTimeFormat.h"
#include "intl/IntlDisplayNames.h"
#include "intl/IntlListFormat.h"
#include "intl/IntlDurationFormat.h"
namespace Escargot {
@ -1263,6 +1264,61 @@ static Value builtinIntlListFormatFormatToParts(ExecutionState& state, Value thi
}
#endif
#if defined(ENABLE_INTL_DURATIONFORMAT)
static Value builtinIntlDurationFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}
Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* realm) -> Object* {
return realm->globalObject()->intlDurationFormatPrototype();
});
if (argc >= 2) {
return new IntlDurationFormatObject(state, proto, argv[0], argv[1]);
} else if (argc >= 1) {
return new IntlDurationFormatObject(state, proto, argv[0], Value());
} else {
return new IntlDurationFormatObject(state, proto, Value(), Value());
}
}
static Value builtinIntlDurationFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
if (!thisValue.isObject() || !thisValue.asObject()->isIntlDurationFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Method called on incompatible receiver");
}
IntlDurationFormatObject* r = thisValue.asObject()->asIntlDurationFormatObject();
return r->resolvedOptions(state);
}
static Value builtinIntlDurationFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
if (!thisValue.isObject() || !thisValue.asObject()->isIntlDurationFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "Method called on incompatible receiver");
}
IntlDurationFormatObject* r = thisValue.asObject()->asIntlDurationFormatObject();
return r->format(state, argv[0]);
}
static Value builtinIntlDurationFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
Value locales = argv[0];
Value options;
if (argc >= 2) {
options = argv[1];
}
const auto& availableLocales = state.context()->vmInstance()->intlDurationFormatAvailableLocales();
ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
}
#endif
static Value builtinIntlGetCanonicalLocales(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
// Let ll be ? CanonicalizeLocaleList(locales).
@ -1778,10 +1834,30 @@ void GlobalObject::installIntl(ExecutionState& state)
m_intlListFormatPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(strings->intlDotListFormat.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
#endif
#if defined(ENABLE_INTL_DURATIONFORMAT)
m_intlDurationFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->DurationFormat, builtinIntlDurationFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
m_intlDurationFormat->setGlobalIntrinsicObject(state);
m_intlDurationFormat->directDefineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlDurationFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
m_intlDurationFormatPrototype = m_intlDurationFormat->getFunctionPrototype(state).asObject();
m_intlDurationFormatPrototype->setGlobalIntrinsicObject(state, true);
m_intlDurationFormatPrototype->directDefineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlDurationFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
m_intlDurationFormatPrototype->directDefineOwnProperty(state, state.context()->staticStrings().format,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->format, builtinIntlDurationFormatFormat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
m_intlDurationFormatPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(strings->intlDotDurationFormat.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
#endif
m_intl->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(state.context()->staticStrings().Intl.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
#endif
m_intl->directDefineOwnProperty(state, ObjectPropertyName(strings->Collator),
ObjectPropertyDescriptor(m_intlCollator, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
@ -1809,6 +1885,10 @@ void GlobalObject::installIntl(ExecutionState& state)
#if defined(ENABLE_INTL_LISTFORMAT)
m_intl->directDefineOwnProperty(state, ObjectPropertyName(strings->ListFormat),
ObjectPropertyDescriptor(m_intlListFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
#endif
#if defined(ENABLE_INTL_DURATIONFORMAT)
m_intl->directDefineOwnProperty(state, ObjectPropertyName(strings->DurationFormat),
ObjectPropertyDescriptor(m_intlDurationFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
#endif
FunctionObject* getCanonicalLocales = new NativeFunctionObject(state, NativeFunctionInfo(strings->getCanonicalLocales, builtinIntlGetCanonicalLocales, 1, NativeFunctionInfo::Strict));
m_intl->directDefineOwnProperty(state, ObjectPropertyName(strings->getCanonicalLocales),

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,143 @@
#if defined(ENABLE_ICU) && defined(ENABLE_INTL) && defined(ENABLE_INTL_DURATIONFORMAT)
/*
* Copyright (c) 2025-present Samsung Electronics Co., Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*/
#ifndef __EscargotIntlDurationFormat__
#define __EscargotIntlDurationFormat__
#include "runtime/Object.h"
#include "runtime/BigInt.h"
namespace Escargot {
// https://tc39.es/ecma402/#sec-todurationrecord
class DurationRecord {
#define FOR_EACH_DURATION_RECORD(F) \
F(years, Years, 0) \
F(months, Months, 1) \
F(weeks, Weeks, 2) \
F(days, Days, 3) \
F(hours, Hours, 4) \
F(minutes, Minutes, 5) \
F(seconds, Seconds, 6) \
F(milliseconds, Milliseconds, 7) \
F(microseconds, Microseconds, 8) \
F(nanoseconds, Nanoseconds, 9)
std::array<double, 10> m_data;
public:
enum class Type : uint8_t {
#define DEFINE_TYPE(name, Name, index) Name,
FOR_EACH_DURATION_RECORD(DEFINE_TYPE)
#undef DEFINE_TYPE
};
DurationRecord()
{
m_data.fill(0);
}
static String* typeName(ExecutionState& state, Type t);
BigIntData totalNanoseconds(DurationRecord::Type type) const;
double operator[](DurationRecord::Type idx) const
{
return m_data[static_cast<unsigned>(idx)];
}
std::array<double, 10>::const_iterator begin() const { return m_data.begin(); }
std::array<double, 10>::const_iterator end() const { return m_data.end(); }
#define DEFINE_GETTER(name, Name, index) \
double name() const { return m_data[index]; }
FOR_EACH_DURATION_RECORD(DEFINE_GETTER)
#undef DEFINE_GETTER
#define DEFINE_SETTER(name, Name, index) \
void set##Name(double v) { m_data[index] = v; }
FOR_EACH_DURATION_RECORD(DEFINE_SETTER)
#undef DEFINE_SETTER
};
class IntlDurationFormatObject : public DerivedObject {
public:
IntlDurationFormatObject(ExecutionState& state, Value locales, Value options);
IntlDurationFormatObject(ExecutionState& state, Object* proto, Value locales, Value options);
virtual bool isIntlDurationFormatObject() const override
{
return true;
}
std::pair<String*, String*> data(size_t index);
Object* resolvedOptions(ExecutionState& state);
String* format(ExecutionState& state, const Value& duration);
protected:
enum class ElementType : uint8_t {
Literal,
Element,
};
struct Element {
ElementType m_type;
bool m_valueSignBit;
DurationRecord::Type m_unit;
UTF16StringDataNonGCStd m_string;
LocalResourcePointer<UFormattedNumber> m_formattedNumber;
};
static std::vector<Element> collectElements(ExecutionState& state, IntlDurationFormatObject* durationFormat, const DurationRecord& duration);
String* m_locale;
String* m_dataLocale;
String* m_dataLocaleWithExtensions;
String* m_numberingSystem;
String* m_style;
String* m_yearsStyle;
String* m_yearsDisplay;
String* m_monthsStyle;
String* m_monthsDisplay;
String* m_weeksStyle;
String* m_weeksDisplay;
String* m_daysStyle;
String* m_daysDisplay;
String* m_hoursStyle;
String* m_hoursDisplay;
String* m_minutesStyle;
String* m_minutesDisplay;
String* m_secondsStyle;
String* m_secondsDisplay;
String* m_millisecondsStyle;
String* m_millisecondsDisplay;
String* m_microsecondsStyle;
String* m_microsecondsDisplay;
String* m_nanosecondsStyle;
String* m_nanosecondsDisplay;
Value m_fractionalDigits;
UListFormatter* m_icuListFormatter;
};
} // namespace Escargot
#endif
#endif

View file

@ -36,12 +36,36 @@ BigIntData::BigIntData(BigIntData&& src)
bf_init(m_data.ctx, &src.m_data);
}
BigIntData::BigIntData(const BigIntData& src)
{
bf_init(ThreadLocal::bfContext(), &m_data);
bf_set(&m_data, &src.m_data);
}
BigIntData& BigIntData::operator=(const BigIntData& src)
{
bf_set(&m_data, &src.m_data);
return *this;
}
BigIntData::BigIntData(const double& d)
{
bf_init(ThreadLocal::bfContext(), &m_data);
bf_set_float64(&m_data, d);
}
BigIntData::BigIntData(const int64_t& d)
{
bf_init(ThreadLocal::bfContext(), &m_data);
bf_set_si(&m_data, d);
}
BigIntData::BigIntData(const uint64_t& d)
{
bf_init(ThreadLocal::bfContext(), &m_data);
bf_set_ui(&m_data, d);
}
BigIntData::BigIntData(String* src, int radix)
{
const auto& bd = src->bufferAccessData();
@ -107,6 +131,83 @@ void BigIntData::init(const char* buf, size_t length, int radix)
}
}
void BigIntData::addition(const int64_t& d)
{
bf_t r;
bf_init(ThreadLocal::bfContext(), &r);
int ret = bf_add_si(&r, &m_data, d, BF_PREC_INF, BF_RNDZ);
if (UNLIKELY(ret)) {
RELEASE_ASSERT_NOT_REACHED();
}
bf_set(&m_data, &r);
bf_delete(&r);
}
void BigIntData::addition(const BigIntData& src)
{
bf_t r;
bf_init(ThreadLocal::bfContext(), &r);
int ret = bf_add(&r, &m_data, &src.m_data, BF_PREC_INF, BF_RNDZ);
if (UNLIKELY(ret)) {
RELEASE_ASSERT_NOT_REACHED();
}
bf_set(&m_data, &r);
bf_delete(&r);
}
void BigIntData::multiply(const int64_t& d)
{
bf_t r;
bf_init(ThreadLocal::bfContext(), &r);
int ret = bf_mul_si(&r, &m_data, d, BF_PREC_INF, BF_RNDZ);
if (UNLIKELY(ret)) {
RELEASE_ASSERT_NOT_REACHED();
}
bf_set(&m_data, &r);
bf_delete(&r);
}
void BigIntData::division(const int64_t& d)
{
int64_t a;
if (bf_get_int64(&a, &m_data, BF_GET_INT_MOD) == 0) {
bf_set_si(&m_data, a / d);
return;
}
bf_t src;
bf_t r;
bf_init(ThreadLocal::bfContext(), &r);
bf_init(ThreadLocal::bfContext(), &src);
bf_set_si(&src, d);
int ret = bf_div(&r, &m_data, &src, BF_PREC_INF, BF_RNDZ);
if (UNLIKELY(ret) && UNLIKELY(ret != BF_ST_INEXACT)) {
RELEASE_ASSERT_NOT_REACHED();
}
bf_set(&m_data, &r);
bf_delete(&r);
bf_delete(&src);
}
void BigIntData::remainder(const int64_t& d)
{
bf_t r, src;
bf_init(ThreadLocal::bfContext(), &r);
bf_init(ThreadLocal::bfContext(), &src);
bf_set_si(&src, d);
int ret = bf_rem(&r, &m_data, &src, BF_PREC_INF, BF_RNDZ,
BF_RNDZ)
& BF_ST_INVALID_OP;
if (UNLIKELY(ret)) {
RELEASE_ASSERT_NOT_REACHED();
}
bf_set(&m_data, &r);
bf_delete(&r);
bf_delete(&src);
}
bool BigIntData::lessThan(BigInt* b) const
{
return bf_cmp_lt(&m_data, &b->m_bf);
@ -117,6 +218,11 @@ bool BigIntData::lessThanEqual(BigInt* b) const
return bf_cmp_le(&m_data, &b->m_bf);
}
bool BigIntData::lessThanEqual(const BigIntData& b) const
{
return bf_cmp_le(&m_data, &b.m_data);
}
bool BigIntData::greaterThan(BigInt* b) const
{
return bf_cmp(&m_data, &b->m_bf) > 0;
@ -127,6 +233,11 @@ bool BigIntData::greaterThanEqual(BigInt* b) const
return bf_cmp(&m_data, &b->m_bf) >= 0;
}
bool BigIntData::greaterThanEqual(const BigIntData& src) const
{
return bf_cmp(&m_data, &src.m_data) >= 0;
}
bool BigIntData::isNaN()
{
return bf_is_nan(&m_data);
@ -137,6 +248,25 @@ bool BigIntData::isInfinity()
return !bf_is_finite(&m_data);
}
std::string BigIntData::toNonGCStdString()
{
int savedSign = m_data.sign;
if (m_data.expn == BF_EXP_ZERO) {
m_data.sign = 0;
}
size_t resultLen = 0;
auto str = bf_ftoa(&resultLen, &m_data, 10, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC | BF_FTOA_JS_QUIRKS);
m_data.sign = savedSign;
if (UNLIKELY(!str)) {
RELEASE_ASSERT_NOT_REACHED();
} else {
std::string ret(str, resultLen);
bf_free(ThreadLocal::bfContext(), str);
return ret;
}
}
void* BigInt::operator new(size_t size)
{
return GC_MALLOC_ATOMIC(size);

View file

@ -30,22 +30,34 @@ class BigIntData {
friend class BigInt;
public:
BigIntData(const uint64_t& d = 0);
BigIntData(const int64_t& d);
BigIntData(const double& d);
BigIntData(String* src, int radix = 10);
BigIntData(const char* buf, size_t length, int radix = 10);
BigIntData(BigIntData&& src);
BigIntData(const BigIntData& src) = delete;
BigIntData operator=(const BigIntData& src) = delete;
BigIntData(const BigIntData& src);
BigIntData& operator=(const BigIntData& src);
~BigIntData();
void addition(const int64_t& d);
void addition(const BigIntData& src);
void multiply(const int64_t& d);
void division(const int64_t& d);
void remainder(const int64_t& d);
bool lessThan(BigInt* b) const;
bool lessThanEqual(BigInt* b) const;
bool lessThanEqual(const BigIntData& b) const;
bool greaterThan(BigInt* b) const;
bool greaterThanEqual(BigInt* b) const;
bool greaterThanEqual(const BigIntData& src) const;
bool isNaN();
bool isInfinity();
std::string toNonGCStdString();
private:
void init(const char* buf, size_t length, int radix);
bf_t m_data;

View file

@ -120,7 +120,13 @@ class FunctionObject;
#else
#define GLOBALOBJECT_BUILTIN_INTL_LISTFORMAT(F, objName)
#endif
#if defined(ENABLE_INTL_DURATIONFORMAT)
#define GLOBALOBJECT_BUILTIN_INTL_DURATIONFORMAT(F, objName) \
F(intlDurationFormat, FunctionObject, objName) \
F(intlDurationFormatPrototype, Object, objName)
#else
#define GLOBALOBJECT_BUILTIN_INTL_DURATIONFORMAT(F, objName)
#endif
#define GLOBALOBJECT_BUILTIN_INTL(F, objName) \
F(intl, Object, objName) \
F(intlCollator, FunctionObject, objName) \
@ -132,7 +138,8 @@ class FunctionObject;
GLOBALOBJECT_BUILTIN_INTL_NUMBERFORMAT(F, objName) \
GLOBALOBJECT_BUILTIN_INTL_PLURALRULES(F, objName) \
GLOBALOBJECT_BUILTIN_INTL_RELATIVETIMEFORMAT(F, objName) \
GLOBALOBJECT_BUILTIN_INTL_LISTFORMAT(F, objName)
GLOBALOBJECT_BUILTIN_INTL_LISTFORMAT(F, objName) \
GLOBALOBJECT_BUILTIN_INTL_DURATIONFORMAT(F, objName)
#else
#define GLOBALOBJECT_BUILTIN_INTL(F, objName)
#endif

View file

@ -95,6 +95,7 @@ class IntlDateTimeFormatObject;
class IntlRelativeTimeFormatObject;
class IntlDisplayNamesObject;
class IntlListFormatObject;
class IntlDurationFormatObject;
#endif
#if defined(ENABLE_WASM)
class WASMModuleObject;
@ -530,6 +531,11 @@ public:
{
return false;
}
virtual bool isIntlDurationFormatObject() const
{
return false;
}
#endif
#if defined(ENABLE_TEMPORAL)
@ -938,6 +944,12 @@ public:
ASSERT(isIntlListFormatObject());
return (IntlListFormatObject*)this;
}
IntlDurationFormatObject* asIntlDurationFormatObject()
{
ASSERT(isIntlDurationFormatObject());
return (IntlDurationFormatObject*)this;
}
#endif
#if defined(ENABLE_TEMPORAL)

View file

@ -135,6 +135,7 @@ void StaticStrings::initStaticStrings()
INIT_STATIC_STRING(intlDotDateTimeFormat, "Intl.DateTimeFormat");
INIT_STATIC_STRING(intlDotRelativeTimeFormat, "Intl.RelativeTimeFormat");
INIT_STATIC_STRING(intlDotNumberFormat, "Intl.NumberFormat");
INIT_STATIC_STRING(intlDotDurationFormat, "Intl.DurationFormat");
INIT_STATIC_STRING(set__proto__, "set __proto__");
INIT_STATIC_STRING(symbolMatch, "[Symbol.match]");
INIT_STATIC_STRING(symbolMatchAll, "[Symbol.matchAll]");

View file

@ -52,6 +52,7 @@ namespace Escargot {
F(Date) \
F(DateTimeFormat) \
F(DisplayNames) \
F(DurationFormat) \
F(E) \
F(EPSILON) \
F(Empty) \
@ -750,9 +751,11 @@ namespace Escargot {
F(DateStyle, "dateStyle") \
F(DateTimeField, "dateTimeField") \
F(Day, "day") \
F(Days, "days") \
F(DayPeriod, "dayPeriod") \
F(Decimal, "decimal") \
F(Dialect, "dialect") \
F(Digital, "digital") \
F(Disjunction, "disjunction") \
F(Engineering, "engineering") \
F(Era, "era") \
@ -767,7 +770,8 @@ namespace Escargot {
F(FormatMatcher, "formatMatcher") \
F(FormatToParts, "formatToParts") \
F(Fraction, "fraction") \
F(FractionDigits, "fractionDigits") \
F(Fractional, "fractional") \
F(FractionalDigits, "fractionalDigits") \
F(FractionalSecond, "fractionalSecond") \
F(FractionalSecondDigits, "fractionalSecondDigits") \
F(Full, "full") \
@ -782,6 +786,7 @@ namespace Escargot {
F(HalfTrunc, "halfTrunc") \
F(HalfEven, "halfEven") \
F(Hour, "hour") \
F(Hours, "hours") \
F(Hour12, "hour12") \
F(HourCycles, "hourCycles") \
F(IgnorePunctuation, "ignorePunctuation") \
@ -803,13 +808,18 @@ namespace Escargot {
F(MaximumFractionDigits, "maximumFractionDigits") \
F(MaximumSignificantDigits, "maximumSignificantDigits") \
F(Medium, "medium") \
F(Milliseconds, "milliseconds") \
F(Microseconds, "microseconds") \
F(MinimumFractionDigits, "minimumFractionDigits") \
F(MinimumIntegerDigits, "minimumIntegerDigits") \
F(MinimumSignificantDigits, "minimumSignificantDigits") \
F(MinusSign, "minusSign") \
F(Minute, "minute") \
F(Minutes, "minutes") \
F(Month, "month") \
F(Months, "months") \
F(MorePrecision, "morePrecision") \
F(Nanoseconds, "nanoseconds") \
F(Narrow, "narrow") \
F(NarrowSymbol, "narrowSymbol") \
F(Negative, "negative") \
@ -828,6 +838,7 @@ namespace Escargot {
F(Quarter, "quarter") \
F(Scientific, "scientific") \
F(Second, "second") \
F(Seconds, "seconds") \
F(Sensitivity, "sensitivity") \
F(SelectRange, "selectRange") \
F(Short, "short") \
@ -858,9 +869,11 @@ namespace Escargot {
F(UseGrouping, "useGrouping") \
F(Variant, "variant") \
F(Week, "week") \
F(Weeks, "weeks") \
F(Weekday, "weekday") \
F(WeekInfo, "weekInfo") \
F(Year, "year") \
F(Years, "years") \
F(YearName, "yearName")
#else
#define FOR_EACH_LAZY_INTL_STATIC_STRING(F)
@ -1025,6 +1038,7 @@ public:
AtomicString intlDotNumberFormat;
AtomicString intlDotDateTimeFormat;
AtomicString intlDotRelativeTimeFormat;
AtomicString intlDotDurationFormat;
AtomicString set__proto__;
AtomicString symbolMatch;
AtomicString symbolMatchAll;

View file

@ -967,6 +967,12 @@ const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& VMInstance::intlLis
return m_intlAvailableLocales;
}
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& VMInstance::intlDurationFormatAvailableLocales()
{
ensureIntlSupportedLocales();
return m_intlAvailableLocales;
}
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& VMInstance::caseMappingAvailableLocales()
{
if (m_caseMappingAvailableLocales.size() == 0) {

View file

@ -386,6 +386,7 @@ public:
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& intlDisplayNamesAvailableLocales();
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& intlListFormatAvailableLocales();
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& intlPluralRulesAvailableLocales();
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& intlDurationFormatAvailableLocales();
const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& caseMappingAvailableLocales();
#endif

View file

@ -194,6 +194,7 @@
#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 ures_getStringByKey RuntimeICUBinder::ICU::instance().ures_getStringByKey
#define unumf_openForSkeletonAndLocale RuntimeICUBinder::ICU::instance().unumf_openForSkeletonAndLocale
#define unumf_openForSkeletonAndLocaleWithError RuntimeICUBinder::ICU::instance().unumf_openForSkeletonAndLocaleWithError

View file

@ -164,6 +164,7 @@ namespace RuntimeICUBinder {
F(ucsdet_detect, const UCharsetMatch*(CALLCONV*)(UCharsetDetector * ucsd, UErrorCode * status), const UCharsetMatch*) \
F(ucsdet_getName, const char*(CALLCONV*)(const UCharsetMatch* ucsm, UErrorCode* status), const char*) \
F(ucsdet_getConfidence, int32_t(CALLCONV*)(const UCharsetMatch* ucsm, UErrorCode* status), int32_t) \
F(ures_open, UResourceBundle*(CALLCONV*)(const char* packageName, const char* locale, UErrorCode* status), UResourceBundle*) \
F(ures_openDirect, UResourceBundle*(CALLCONV*)(const char* packageName, const char* locale, UErrorCode* status), UResourceBundle*) \
F(ures_getByKey, UResourceBundle*(CALLCONV*)(const UResourceBundle* resourceBundle, const char* key, UResourceBundle* fillIn, UErrorCode* status), UResourceBundle*) \
F(ures_getKey, const char*(CALLCONV*)(const UResourceBundle* resourceBundle), const char*) \
@ -171,6 +172,7 @@ namespace RuntimeICUBinder {
F(ures_hasNext, UBool(CALLCONV*)(const UResourceBundle* resourceBundle), UBool) \
F(ures_getSize, int32_t(CALLCONV*)(const UResourceBundle* resourceBundle), int32_t) \
F(ures_getStringByIndex, const UChar*(CALLCONV*)(const UResourceBundle* resourceBundle, int32_t indexS, int32_t* len, UErrorCode* status), const UChar*) \
F(ures_getStringByKey, const UChar*(CALLCONV*)(const UResourceBundle *resB, const char *key, int32_t *len, UErrorCode *status), const UChar*) \
F(uplrules_select, int32_t(CALLCONV*)(const UPluralRules* uplrules, double number, UChar* keyword, int32_t capacity, UErrorCode* status), int32_t) \
F(uplrules_getKeywords, UEnumeration*(CALLCONV*)(const UPluralRules* uplrules, UErrorCode* status), UEnumeration*) \
F(uplrules_open, UPluralRules*(CALLCONV*)(const char* locale, UErrorCode* status), UPluralRules*) \

View file

@ -4626,74 +4626,10 @@
<test id="intl402/DateTimeFormat/timezone-not-canonicalized"><reason>TODO</reason></test>
<test id="intl402/DisplayNames/prototype/of/type-calendar-invalid"><reason>TODO</reason></test>
<test id="intl402/DisplayNames/prototype/of/type-language-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-locales-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-locales-valid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-option-read-order"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-defaults"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-fractionalDigits-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-fractionalDigits-valid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-localeMatcher-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-localeMatcher-valid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-numberingSystem-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-numberingSystem-valid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-order"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-style-conflict"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-style-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-options-style-valid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/constructor-unit-style-defaults"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/extensibility"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/length"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/name"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/newtarget-undefined"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prop-desc"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/constructor/prop-desc"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/constructor/value"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/branding"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/digital-style-with-hours-display-auto-with-zero-hour"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/duration-out-of-range-1"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/duration-out-of-range-2"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/duration-out-of-range-3"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/duration-out-of-range-4"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/fractions-of-subsecond-units-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/invalid-arguments-throws"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/invalid-negative-duration-throws"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/length"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/mixed-non-numeric-styles-es"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/mixed-short-and-numeric"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/name"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-style-default-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-style-short-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-with-leading-zero-style-default-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-with-leading-zero-style-digital-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-with-leading-zero-style-long-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-with-leading-zero-style-narrow-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-duration-with-leading-zero-style-short-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-durationstyle-digital-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-durationstyle-long-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-durationstyle-narrow-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/negative-zero"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/not-a-constructor"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/numeric-hour-with-zero-minutes-and-non-zero-seconds"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/numeric-hour-with-zero-minutes-and-non-zero-seconds-with-auto-display"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/numeric-hour-with-zero-minutes-and-non-zero-seconds-with-auto-display-and-zero-fractional"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/precision-exact-mathematical-values"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/prop-desc"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/rounding-mode-trunc-for-seconds"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-default-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-digital-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-digital-fractionalDigits-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-digital-fractionalDigits-undefined-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-digital-large-hms-values"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-digital-largenumber-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-long-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-narrow-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/style-short-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/taint-temporal-duration-prototype"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/temporal-duration-object-arg"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/temporal-duration-string-arg"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/format/throw-invoked-as-func"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/formatToParts/branding"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/formatToParts/formatToParts-style-default-en"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/formatToParts/formatToParts-style-digital-en"><reason>TODO</reason></test>
@ -4720,23 +4656,6 @@
<test id="intl402/DurationFormat/prototype/formatToParts/temporal-duration-object-arg"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/formatToParts/temporal-duration-string-arg"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/formatToParts/throw-invoked-as-func"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/prototype_attributes"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/length"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/name"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/prop-desc"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/resolved-numbering-system-unicode-extensions-and-options"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/return-keys-order-default"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/resolvedOptions/throw-invoked-as-func"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/toStringTag/toString"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/prototype/toStringTag/toStringTag"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/basic"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/branding"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/length"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/locales-empty"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/locales-invalid"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/locales-specific"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/name"><reason>TODO</reason></test>
<test id="intl402/DurationFormat/supportedLocalesOf/prop-desc"><reason>TODO</reason></test>
<test id="intl402/Intl/DateTimeFormat/prototype/formatRange/fails-on-distinct-temporal-types"><reason>TODO</reason></test>
<test id="intl402/Intl/DateTimeFormat/prototype/formatRangeToParts/fails-on-distinct-temporal-types"><reason>TODO</reason></test>
<test id="intl402/Intl/getCanonicalLocales/complex-region-subtag-replacement"><reason>TODO</reason></test>