[Intl] Intl.NumberFormat Unified API Proposal
Design Doc: https://goo.gl/ZAtL1f Bug: v8:8515 Change-Id: I543ab704fd3f8b41e396879ebbc581977ec0ff10 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1612325 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/master@{#61709}
This commit is contained in:
parent
1bc7124667
commit
5efc4d0b74
@ -213,10 +213,11 @@ DEFINE_IMPLICATION(harmony_import_meta, harmony_dynamic_import)
|
||||
V(harmony_weak_refs, "harmony weak references")
|
||||
|
||||
#ifdef V8_INTL_SUPPORT
|
||||
#define HARMONY_INPROGRESS(V) \
|
||||
HARMONY_INPROGRESS_BASE(V) \
|
||||
V(harmony_intl_add_calendar_numbering_system, \
|
||||
"Add calendar and numberingSystem to DateTimeFormat")
|
||||
#define HARMONY_INPROGRESS(V) \
|
||||
HARMONY_INPROGRESS_BASE(V) \
|
||||
V(harmony_intl_add_calendar_numbering_system, \
|
||||
"Add calendar and numberingSystem to DateTimeFormat") \
|
||||
V(harmony_intl_numberformat_unified, "Unified Intl.NumberFormat Features")
|
||||
#else
|
||||
#define HARMONY_INPROGRESS(V) HARMONY_INPROGRESS_BASE(V)
|
||||
#endif
|
||||
|
@ -18,8 +18,10 @@
|
||||
V(_, current_string, "current") \
|
||||
V(_, collation_string, "collation") \
|
||||
V(_, compact_string, "compact") \
|
||||
V(_, compactDisplay_string, "compactDisplay") \
|
||||
V(_, currency_string, "currency") \
|
||||
V(_, currencyDisplay_string, "currencyDisplay") \
|
||||
V(_, currencySign_string, "currencySign") \
|
||||
V(_, dateStyle_string, "dateStyle") \
|
||||
V(_, day_string, "day") \
|
||||
V(_, dayPeriod_string, "dayPeriod") \
|
||||
@ -69,6 +71,7 @@
|
||||
V(_, narrow_symbol_string, "narrow-symbol") \
|
||||
V(_, never_string, "never") \
|
||||
V(_, none_string, "none") \
|
||||
V(_, notation_string, "notation") \
|
||||
V(_, normal_string, "normal") \
|
||||
V(_, numberingSystem_string, "numberingSystem") \
|
||||
V(_, numeric_string, "numeric") \
|
||||
@ -84,6 +87,7 @@
|
||||
V(_, sensitivity_string, "sensitivity") \
|
||||
V(_, sep_string, "sep") \
|
||||
V(_, shared_string, "shared") \
|
||||
V(_, signDisplay_string, "signDisplay") \
|
||||
V(_, standard_string, "standard") \
|
||||
V(_, startRange_string, "startRange") \
|
||||
V(_, strict_string, "strict") \
|
||||
@ -99,6 +103,7 @@
|
||||
V(_, useGrouping_string, "useGrouping") \
|
||||
V(_, UTC_string, "UTC") \
|
||||
V(_, unit_string, "unit") \
|
||||
V(_, unitDisplay_string, "unitDisplay") \
|
||||
V(_, weekday_string, "weekday") \
|
||||
V(_, year_string, "year")
|
||||
#else // V8_INTL_SUPPORT
|
||||
|
@ -4239,6 +4239,7 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_hashbang)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_add_calendar_numbering_system)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_bigint)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_datetime_style)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_numberformat_unified)
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
#undef EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE
|
||||
|
@ -118,6 +118,162 @@ UNumberUnitWidth ToUNumberUnitWidth(CurrencyDisplay currency_display) {
|
||||
}
|
||||
}
|
||||
|
||||
UNumberUnitWidth ToUNumberUnitWidth(UnitDisplay unit_display) {
|
||||
switch (unit_display) {
|
||||
case UnitDisplay::SHORT:
|
||||
return UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT;
|
||||
case UnitDisplay::LONG:
|
||||
return UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME;
|
||||
case UnitDisplay::NARROW:
|
||||
return UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW;
|
||||
}
|
||||
}
|
||||
|
||||
UNumberSignDisplay ToUNumberSignDisplay(SignDisplay sign_display,
|
||||
CurrencySign currency_sign) {
|
||||
switch (sign_display) {
|
||||
case SignDisplay::AUTO:
|
||||
if (currency_sign == CurrencySign::ACCOUNTING) {
|
||||
return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING;
|
||||
}
|
||||
DCHECK(currency_sign == CurrencySign::STANDARD);
|
||||
return UNumberSignDisplay::UNUM_SIGN_AUTO;
|
||||
case SignDisplay::NEVER:
|
||||
return UNumberSignDisplay::UNUM_SIGN_NEVER;
|
||||
case SignDisplay::ALWAYS:
|
||||
if (currency_sign == CurrencySign::ACCOUNTING) {
|
||||
return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS;
|
||||
}
|
||||
DCHECK(currency_sign == CurrencySign::STANDARD);
|
||||
return UNumberSignDisplay::UNUM_SIGN_ALWAYS;
|
||||
case SignDisplay::EXCEPT_ZERO:
|
||||
if (currency_sign == CurrencySign::ACCOUNTING) {
|
||||
return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
|
||||
}
|
||||
DCHECK(currency_sign == CurrencySign::STANDARD);
|
||||
return UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
icu::number::Notation ToICUNotation(Notation notation,
|
||||
CompactDisplay compact_display) {
|
||||
switch (notation) {
|
||||
case Notation::STANDARD:
|
||||
return icu::number::Notation::simple();
|
||||
case Notation::SCIENTIFIC:
|
||||
return icu::number::Notation::scientific();
|
||||
case Notation::ENGINEERING:
|
||||
return icu::number::Notation::engineering();
|
||||
case Notation::COMPACT:
|
||||
if (compact_display == CompactDisplay::SHORT) {
|
||||
return icu::number::Notation::compactShort();
|
||||
}
|
||||
DCHECK(compact_display == CompactDisplay::LONG);
|
||||
return icu::number::Notation::compactLong();
|
||||
}
|
||||
}
|
||||
|
||||
std::map<const std::string, icu::MeasureUnit> CreateUnitMap() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t total = icu::MeasureUnit::getAvailable(nullptr, 0, status);
|
||||
CHECK(U_FAILURE(status));
|
||||
status = U_ZERO_ERROR;
|
||||
// See the list in ecma402 #sec-issanctionedsimpleunitidentifier
|
||||
std::set<std::string> sanctioned(
|
||||
{"acre", "bit", "byte", "celsius",
|
||||
"centimeter", "day", "degree", "fahrenheit",
|
||||
"foot", "gigabit", "gigabyte", "gram",
|
||||
"hectare", "hour", "inch", "kilobit",
|
||||
"kilobyte", "kilogram", "kilometer", "megabit",
|
||||
"megabyte", "meter", "mile", "mile-scandinavian",
|
||||
"millimeter", "millisecond", "minute", "month",
|
||||
"ounce", "percent", "petabyte", "pound",
|
||||
"second", "stone", "terabit", "terabyte",
|
||||
"week", "yard", "year"});
|
||||
std::vector<icu::MeasureUnit> units(total);
|
||||
total = icu::MeasureUnit::getAvailable(units.data(), total, status);
|
||||
CHECK(U_SUCCESS(status));
|
||||
std::map<const std::string, icu::MeasureUnit> map;
|
||||
for (auto it = units.begin(); it != units.end(); ++it) {
|
||||
if (sanctioned.count(it->getSubtype()) > 0) {
|
||||
map[it->getSubtype()] = *it;
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
class UnitFactory {
|
||||
public:
|
||||
UnitFactory() : map_(CreateUnitMap()) {}
|
||||
virtual ~UnitFactory() {}
|
||||
|
||||
// ecma402 #sec-issanctionedsimpleunitidentifier
|
||||
icu::MeasureUnit create(const std::string& unitIdentifier) {
|
||||
// 1. If unitIdentifier is in the following list, return true.
|
||||
auto found = map_.find(unitIdentifier);
|
||||
if (found != map_.end()) {
|
||||
return found->second;
|
||||
}
|
||||
// 2. Return false.
|
||||
return icu::NoUnit::base();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<const std::string, icu::MeasureUnit> map_;
|
||||
};
|
||||
|
||||
// ecma402 #sec-issanctionedsimpleunitidentifier
|
||||
icu::MeasureUnit IsSanctionedUnitIdentifier(const std::string& unit) {
|
||||
static base::LazyInstance<UnitFactory>::type factory =
|
||||
LAZY_INSTANCE_INITIALIZER;
|
||||
return factory.Pointer()->create(unit);
|
||||
}
|
||||
|
||||
// ecma402 #sec-iswellformedunitidentifier
|
||||
Maybe<std::pair<icu::MeasureUnit, icu::MeasureUnit>> IsWellFormedUnitIdentifier(
|
||||
Isolate* isolate, const std::string& unit) {
|
||||
icu::MeasureUnit result = IsSanctionedUnitIdentifier(unit);
|
||||
icu::MeasureUnit none = icu::NoUnit::base();
|
||||
// 1. If the result of IsSanctionedUnitIdentifier(unitIdentifier) is true,
|
||||
// then
|
||||
if (result != none) {
|
||||
// a. Return true.
|
||||
std::pair<icu::MeasureUnit, icu::MeasureUnit> pair(result, none);
|
||||
return Just(pair);
|
||||
}
|
||||
// 2. If the substring "-per-" does not occur exactly once in unitIdentifier,
|
||||
// then
|
||||
size_t first_per = unit.find("-per-");
|
||||
if (first_per == std::string::npos ||
|
||||
unit.find("-per-", first_per + 5) != std::string::npos) {
|
||||
// a. Return false.
|
||||
return Nothing<std::pair<icu::MeasureUnit, icu::MeasureUnit>>();
|
||||
}
|
||||
// 3. Let numerator be the substring of unitIdentifier from the beginning to
|
||||
// just before "-per-".
|
||||
std::string numerator = unit.substr(0, first_per);
|
||||
|
||||
// 4. If the result of IsSanctionedUnitIdentifier(numerator) is false, then
|
||||
result = IsSanctionedUnitIdentifier(numerator);
|
||||
if (result == none) {
|
||||
// a. Return false.
|
||||
return Nothing<std::pair<icu::MeasureUnit, icu::MeasureUnit>>();
|
||||
}
|
||||
// 5. Let denominator be the substring of unitIdentifier from just after
|
||||
// "-per-" to the end.
|
||||
std::string denominator = unit.substr(first_per + 5);
|
||||
|
||||
// 6. If the result of IsSanctionedUnitIdentifier(denominator) is false, then
|
||||
icu::MeasureUnit den_result = IsSanctionedUnitIdentifier(denominator);
|
||||
if (den_result == none) {
|
||||
// a. Return false.
|
||||
return Nothing<std::pair<icu::MeasureUnit, icu::MeasureUnit>>();
|
||||
}
|
||||
// 7. Return true.
|
||||
std::pair<icu::MeasureUnit, icu::MeasureUnit> pair(result, den_result);
|
||||
return Just(pair);
|
||||
}
|
||||
|
||||
// ecma-402/#sec-currencydigits
|
||||
// The currency is expected to an all upper case string value.
|
||||
int CurrencyDigits(const icu::UnicodeString& currency) {
|
||||
@ -149,24 +305,40 @@ bool IsWellFormedCurrencyCode(const std::string& currency) {
|
||||
}
|
||||
|
||||
// Parse the 'style' from the skeleton.
|
||||
Handle<String> StyleString(Isolate* isolate,
|
||||
const icu::UnicodeString& skeleton) {
|
||||
Style StyleFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "percent precision-integer rounding-mode-half-up scale/100"
|
||||
if (skeleton.indexOf("percent") >= 0) {
|
||||
return ReadOnlyRoots(isolate).percent_string_handle();
|
||||
if (skeleton.indexOf("percent") >= 0 && skeleton.indexOf("scale/100") >= 0) {
|
||||
return Style::PERCENT;
|
||||
}
|
||||
// Ex: skeleton as "currency/TWD .00 rounding-mode-half-up"
|
||||
if (skeleton.indexOf("currency") >= 0) {
|
||||
return ReadOnlyRoots(isolate).currency_string_handle();
|
||||
return Style::CURRENCY;
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "measure-unit/length-meter .### rounding-mode-half-up unit-width-narrow"
|
||||
if (skeleton.indexOf("measure-unit") >= 0) {
|
||||
return ReadOnlyRoots(isolate).unit_string_handle();
|
||||
// or special case for "percent .### rounding-mode-half-up"
|
||||
if (skeleton.indexOf("measure-unit") >= 0 ||
|
||||
skeleton.indexOf("percent") >= 0) {
|
||||
return Style::UNIT;
|
||||
}
|
||||
// Ex: skeleton as ".### rounding-mode-half-up"
|
||||
return ReadOnlyRoots(isolate).decimal_string_handle();
|
||||
return Style::DECIMAL;
|
||||
}
|
||||
|
||||
// Return the style as a String.
|
||||
Handle<String> StyleAsString(Isolate* isolate, Style style) {
|
||||
switch (style) {
|
||||
case Style::PERCENT:
|
||||
return ReadOnlyRoots(isolate).percent_string_handle();
|
||||
case Style::CURRENCY:
|
||||
return ReadOnlyRoots(isolate).currency_string_handle();
|
||||
case Style::UNIT:
|
||||
return ReadOnlyRoots(isolate).unit_string_handle();
|
||||
case Style::DECIMAL:
|
||||
return ReadOnlyRoots(isolate).decimal_string_handle();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// Parse the 'currencyDisplay' from the skeleton.
|
||||
@ -178,7 +350,7 @@ Handle<String> CurrencyDisplayString(Isolate* isolate,
|
||||
return ReadOnlyRoots(isolate).code_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "currency/TWD .00 rounding-mode-half-up unit-width-full-name;
|
||||
// "currency/TWD .00 rounding-mode-half-up unit-width-full-name;"
|
||||
if (skeleton.indexOf("unit-width-full-name") >= 0) {
|
||||
return ReadOnlyRoots(isolate).name_string_handle();
|
||||
}
|
||||
@ -197,7 +369,7 @@ bool UseGroupingFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
}
|
||||
|
||||
// Parse currency code from skeleton. For example, skeleton as
|
||||
// "currency/TWD .00 rounding-mode-half-up unit-width-full-name;
|
||||
// "currency/TWD .00 rounding-mode-half-up unit-width-full-name;"
|
||||
std::string CurrencyFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
std::string str;
|
||||
str = skeleton.toUTF8String<std::string>(str);
|
||||
@ -207,6 +379,112 @@ std::string CurrencyFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
return str.substr(index + search.size(), 3);
|
||||
}
|
||||
|
||||
// Return CurrencySign as string based on skeleton.
|
||||
Handle<String> CurrencySignString(Isolate* isolate,
|
||||
const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-accounting-always" OR
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-accounting-except-zero"
|
||||
if (skeleton.indexOf("sign-accounting") >= 0) {
|
||||
return ReadOnlyRoots(isolate).accounting_string_handle();
|
||||
}
|
||||
return ReadOnlyRoots(isolate).standard_string_handle();
|
||||
}
|
||||
|
||||
// Return UnitDisplay as string based on skeleton.
|
||||
Handle<String> UnitDisplayString(Isolate* isolate,
|
||||
const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "measure-unit/length-meter .### rounding-mode-half-up unit-width-full-name"
|
||||
if (skeleton.indexOf("unit-width-full-name") >= 0) {
|
||||
return ReadOnlyRoots(isolate).long_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "measure-unit/length-meter .### rounding-mode-half-up unit-width-narrow".
|
||||
if (skeleton.indexOf("unit-width-narrow") >= 0) {
|
||||
return ReadOnlyRoots(isolate).narrow_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "measure-unit/length-foot .### rounding-mode-half-up"
|
||||
return ReadOnlyRoots(isolate).short_string_handle();
|
||||
}
|
||||
|
||||
// Parse Notation from skeleton.
|
||||
Notation NotationFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "scientific .### rounding-mode-half-up"
|
||||
if (skeleton.indexOf("scientific") >= 0) {
|
||||
return Notation::SCIENTIFIC;
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "engineering .### rounding-mode-half-up"
|
||||
if (skeleton.indexOf("engineering") >= 0) {
|
||||
return Notation::ENGINEERING;
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "compact-short .### rounding-mode-half-up" or
|
||||
// "compact-long .### rounding-mode-half-up
|
||||
if (skeleton.indexOf("compact-") >= 0) {
|
||||
return Notation::COMPACT;
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "measure-unit/length-foot .### rounding-mode-half-up"
|
||||
return Notation::STANDARD;
|
||||
}
|
||||
|
||||
Handle<String> NotationAsString(Isolate* isolate, Notation notation) {
|
||||
switch (notation) {
|
||||
case Notation::SCIENTIFIC:
|
||||
return ReadOnlyRoots(isolate).scientific_string_handle();
|
||||
case Notation::ENGINEERING:
|
||||
return ReadOnlyRoots(isolate).engineering_string_handle();
|
||||
case Notation::COMPACT:
|
||||
return ReadOnlyRoots(isolate).compact_string_handle();
|
||||
case Notation::STANDARD:
|
||||
return ReadOnlyRoots(isolate).standard_string_handle();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// Return CompactString as string based on skeleton.
|
||||
Handle<String> CompactDisplayString(Isolate* isolate,
|
||||
const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "compact-long .### rounding-mode-half-up"
|
||||
if (skeleton.indexOf("compact-long") >= 0) {
|
||||
return ReadOnlyRoots(isolate).long_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "compact-short .### rounding-mode-half-up"
|
||||
DCHECK_GE(skeleton.indexOf("compact-short"), 0);
|
||||
return ReadOnlyRoots(isolate).short_string_handle();
|
||||
}
|
||||
|
||||
// Return SignDisplay as string based on skeleton.
|
||||
Handle<String> SignDisplayString(Isolate* isolate,
|
||||
const icu::UnicodeString& skeleton) {
|
||||
// Ex: skeleton as
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-never"
|
||||
if (skeleton.indexOf("sign-never") >= 0) {
|
||||
return ReadOnlyRoots(isolate).never_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// ".### rounding-mode-half-up sign-always" or
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-accounting-always"
|
||||
if (skeleton.indexOf("sign-always") >= 0 ||
|
||||
skeleton.indexOf("sign-accounting-always") >= 0) {
|
||||
return ReadOnlyRoots(isolate).always_string_handle();
|
||||
}
|
||||
// Ex: skeleton as
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-accounting-except-zero" or
|
||||
// "currency/TWD .00 rounding-mode-half-up sign-except-zero"
|
||||
if (skeleton.indexOf("sign-accounting-except-zero") >= 0 ||
|
||||
skeleton.indexOf("sign-except-zero") >= 0) {
|
||||
return ReadOnlyRoots(isolate).except_zero_string_handle();
|
||||
}
|
||||
return ReadOnlyRoots(isolate).auto_string_handle();
|
||||
}
|
||||
|
||||
// Return the minimum integer digits by counting the number of '0' after
|
||||
// "integer-width/+" in the skeleton.
|
||||
// Ex: Return 15 for skeleton as
|
||||
@ -283,6 +561,73 @@ bool SignificantDigitsFromSkeleton(const icu::UnicodeString& skeleton,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ex: percent .### rounding-mode-half-up
|
||||
// Special case for "percent"
|
||||
// Ex: "measure-unit/length-kilometer per-measure-unit/duration-hour .###
|
||||
// rounding-mode-half-up" should return "kilometer-per-unit".
|
||||
// Ex: "measure-unit/duration-year .### rounding-mode-half-up" should return
|
||||
// "year".
|
||||
std::string UnitFromSkeleton(const icu::UnicodeString& skeleton) {
|
||||
std::string str;
|
||||
str = skeleton.toUTF8String<std::string>(str);
|
||||
// Special case for "percent" first.
|
||||
if (str.find("percent") != str.npos) {
|
||||
return "percent";
|
||||
}
|
||||
std::string search("measure-unit/");
|
||||
size_t begin = str.find(search);
|
||||
if (begin == str.npos) {
|
||||
return "";
|
||||
}
|
||||
// Skip the type (ex: "length").
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// b
|
||||
begin = str.find("-", begin + search.size());
|
||||
if (begin == str.npos) {
|
||||
return "";
|
||||
}
|
||||
begin++; // Skip the '-'.
|
||||
// Find the end of the subtype.
|
||||
size_t end = str.find(" ", begin);
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// b e
|
||||
if (end == str.npos) {
|
||||
end = str.size();
|
||||
return str.substr(begin, end - begin);
|
||||
}
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// b e
|
||||
// [result ]
|
||||
std::string result = str.substr(begin, end - begin);
|
||||
begin = end + 1;
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// [result ]eb
|
||||
std::string search_per("per-measure-unit/");
|
||||
begin = str.find(search_per, begin);
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// [result ]e b
|
||||
if (begin == str.npos) {
|
||||
return result;
|
||||
}
|
||||
// Skip the type (ex: "duration").
|
||||
begin = str.find("-", begin + search_per.size());
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// [result ]e b
|
||||
if (begin == str.npos) {
|
||||
return result;
|
||||
}
|
||||
begin++; // Skip the '-'.
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// [result ]e b
|
||||
end = str.find(" ", begin);
|
||||
if (end == str.npos) {
|
||||
end = str.size();
|
||||
}
|
||||
// "measure-unit/length-kilometer per-measure-unit/duration-hour"
|
||||
// [result ] b e
|
||||
return result + "-per-" + str.substr(begin, end - begin);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// static
|
||||
@ -335,9 +680,10 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
Style style = StyleFromSkeleton(skeleton);
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->style_string(),
|
||||
StyleString(isolate, skeleton), Just(kDontThrow))
|
||||
StyleAsString(isolate, style), Just(kDontThrow))
|
||||
.FromJust());
|
||||
std::string currency = CurrencyFromSkeleton(skeleton);
|
||||
if (!currency.empty()) {
|
||||
@ -351,7 +697,31 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
isolate, options, factory->currencyDisplay_string(),
|
||||
CurrencyDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->currencySign_string(),
|
||||
CurrencySignString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
std::string unit = UnitFromSkeleton(skeleton);
|
||||
if (!unit.empty()) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->unit_string(),
|
||||
isolate->factory()->NewStringFromAsciiChecked(unit.c_str()),
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
if (style == Style::UNIT || style == Style::PERCENT) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->unitDisplay_string(),
|
||||
UnitDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(
|
||||
JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->minimumIntegerDigits_string(),
|
||||
@ -359,7 +729,10 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
int32_t minimum = 0, maximum = 0;
|
||||
if (!FractionDigitsFromSkeleton(skeleton, &minimum, &maximum)) {
|
||||
bool output_fraction =
|
||||
FractionDigitsFromSkeleton(skeleton, &minimum, &maximum);
|
||||
|
||||
if (!FLAG_harmony_intl_numberformat_unified && !output_fraction) {
|
||||
// Currenct ECMA 402 spec mandate to record (Min|Max)imumFractionDigits
|
||||
// uncondictionally while the unified number proposal eventually will only
|
||||
// record either (Min|Max)imumFractionDigits or
|
||||
@ -371,17 +744,20 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
// present.
|
||||
// TODO(ftang) remove the following two lines once we ship
|
||||
// int-number-format-unified
|
||||
output_fraction = true;
|
||||
minimum = number_format->minimum_fraction_digits();
|
||||
maximum = number_format->maximum_fraction_digits();
|
||||
}
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->minimumFractionDigits_string(),
|
||||
factory->NewNumberFromInt(minimum), Just(kDontThrow))
|
||||
.FromJust());
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->maximumFractionDigits_string(),
|
||||
factory->NewNumberFromInt(maximum), Just(kDontThrow))
|
||||
.FromJust());
|
||||
if (output_fraction) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->minimumFractionDigits_string(),
|
||||
factory->NewNumberFromInt(minimum), Just(kDontThrow))
|
||||
.FromJust());
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->maximumFractionDigits_string(),
|
||||
factory->NewNumberFromInt(maximum), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
minimum = 0;
|
||||
maximum = 0;
|
||||
if (SignificantDigitsFromSkeleton(skeleton, &minimum, &maximum)) {
|
||||
@ -400,6 +776,24 @@ Handle<JSObject> JSNumberFormat::ResolvedOptions(
|
||||
factory->ToBoolean(UseGroupingFromSkeleton(skeleton)),
|
||||
Just(kDontThrow))
|
||||
.FromJust());
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
Notation notation = NotationFromSkeleton(skeleton);
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->notation_string(),
|
||||
NotationAsString(isolate, notation), Just(kDontThrow))
|
||||
.FromJust());
|
||||
// Only output compactDisplay when notation is compact.
|
||||
if (notation == Notation::COMPACT) {
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->compactDisplay_string(),
|
||||
CompactDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
CHECK(JSReceiver::CreateDataProperty(
|
||||
isolate, options, factory->signDisplay_string(),
|
||||
SignDisplayString(isolate, skeleton), Just(kDontThrow))
|
||||
.FromJust());
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -437,7 +831,6 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
Isolate* isolate, Handle<JSNumberFormat> number_format,
|
||||
Handle<Object> locales, Handle<Object> options_obj) {
|
||||
number_format->set_flags(0);
|
||||
// set the flags to 0 ASAP.
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
// 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
|
||||
@ -508,13 +901,25 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
number_format->set_locale(*locale_str);
|
||||
|
||||
// 11. Let dataLocale be r.[[dataLocale]].
|
||||
//
|
||||
|
||||
icu::number::LocalizedNumberFormatter icu_number_formatter =
|
||||
icu::number::NumberFormatter::withLocale(r.icu_locale)
|
||||
.roundingMode(UNUM_ROUND_HALFUP);
|
||||
|
||||
// 12. Let style be ? GetOption(options, "style", "string", « "decimal",
|
||||
// "percent", "currency" », "decimal").
|
||||
const char* service = "Intl.NumberFormat";
|
||||
|
||||
std::vector<const char*> style_str_values({"decimal", "percent", "currency"});
|
||||
std::vector<Style> style_enum_values(
|
||||
{Style::DECIMAL, Style::PERCENT, Style::CURRENCY});
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
style_str_values.push_back("unit");
|
||||
style_enum_values.push_back(Style::UNIT);
|
||||
}
|
||||
Maybe<Style> maybe_style = Intl::GetStringOption<Style>(
|
||||
isolate, options, "style", service, {"decimal", "percent", "currency"},
|
||||
{Style::DECIMAL, Style::PERCENT, Style::CURRENCY}, Style::DECIMAL);
|
||||
isolate, options, "style", service, style_str_values, style_enum_values,
|
||||
Style::DECIMAL);
|
||||
MAYBE_RETURN(maybe_style, MaybeHandle<JSNumberFormat>());
|
||||
Style style = maybe_style.FromJust();
|
||||
|
||||
@ -565,19 +970,106 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
|
||||
// 18. Let currencyDisplay be ? GetOption(options, "currencyDisplay",
|
||||
// "string", « "code", "symbol", "name" », "symbol").
|
||||
Maybe<CurrencyDisplay> maybe_currencyDisplay =
|
||||
std::vector<const char*> currency_display_str_values(
|
||||
{"code", "symbol", "name"});
|
||||
std::vector<CurrencyDisplay> currency_display_enum_values(
|
||||
{CurrencyDisplay::CODE, CurrencyDisplay::SYMBOL, CurrencyDisplay::NAME});
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
currency_display_str_values.push_back("narrow-symbol");
|
||||
currency_display_enum_values.push_back(CurrencyDisplay::NARROW_SYMBOL);
|
||||
}
|
||||
Maybe<CurrencyDisplay> maybe_currency_display =
|
||||
Intl::GetStringOption<CurrencyDisplay>(
|
||||
isolate, options, "currencyDisplay", service,
|
||||
{"code", "symbol", "name"},
|
||||
{CurrencyDisplay::CODE, CurrencyDisplay::SYMBOL,
|
||||
CurrencyDisplay::NAME},
|
||||
currency_display_str_values, currency_display_enum_values,
|
||||
CurrencyDisplay::SYMBOL);
|
||||
MAYBE_RETURN(maybe_currencyDisplay, MaybeHandle<JSNumberFormat>());
|
||||
CurrencyDisplay currency_display = maybe_currencyDisplay.FromJust();
|
||||
MAYBE_RETURN(maybe_currency_display, MaybeHandle<JSNumberFormat>());
|
||||
CurrencyDisplay currency_display = maybe_currency_display.FromJust();
|
||||
|
||||
CurrencySign currency_sign = CurrencySign::STANDARD;
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
// Let currencySign be ? GetOption(options, "currencySign", "string", «
|
||||
// "standard", "accounting" », "standard").
|
||||
Maybe<CurrencySign> maybe_currency_sign =
|
||||
Intl::GetStringOption<CurrencySign>(
|
||||
isolate, options, "currencySign", service,
|
||||
{"standard", "accounting"},
|
||||
{CurrencySign::STANDARD, CurrencySign::ACCOUNTING},
|
||||
CurrencySign::STANDARD);
|
||||
MAYBE_RETURN(maybe_currency_sign, MaybeHandle<JSNumberFormat>());
|
||||
currency_sign = maybe_currency_sign.FromJust();
|
||||
|
||||
// Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
|
||||
std::unique_ptr<char[]> unit_cstr;
|
||||
Maybe<bool> found_unit = Intl::GetStringOption(
|
||||
isolate, options, "unit", empty_values, service, &unit_cstr);
|
||||
MAYBE_RETURN(found_unit, MaybeHandle<JSNumberFormat>());
|
||||
|
||||
std::string unit;
|
||||
if (found_unit.FromJust()) {
|
||||
DCHECK_NOT_NULL(unit_cstr.get());
|
||||
unit = unit_cstr.get();
|
||||
}
|
||||
|
||||
// Let unitDisplay be ? GetOption(options, "unitDisplay", "string", «
|
||||
// "short", "narrow", "long" », "short").
|
||||
Maybe<UnitDisplay> maybe_unit_display = Intl::GetStringOption<UnitDisplay>(
|
||||
isolate, options, "unitDisplay", service, {"short", "narrow", "long"},
|
||||
{UnitDisplay::SHORT, UnitDisplay::NARROW, UnitDisplay::LONG},
|
||||
UnitDisplay::SHORT);
|
||||
MAYBE_RETURN(maybe_unit_display, MaybeHandle<JSNumberFormat>());
|
||||
UnitDisplay unit_display = maybe_unit_display.FromJust();
|
||||
|
||||
// If style is "percent", then
|
||||
if (style == Style::PERCENT) {
|
||||
// Let unit be "concentr-percent".
|
||||
unit = "percent";
|
||||
}
|
||||
// If style is "unit" or "percent", then
|
||||
if (style == Style::PERCENT || style == Style::UNIT) {
|
||||
// If unit is undefined, throw a TypeError exception.
|
||||
if (unit == "") {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kInvalidUnit,
|
||||
factory->NewStringFromStaticChars("Intl.NumberFormat"),
|
||||
factory->NewStringFromStaticChars("")),
|
||||
JSNumberFormat);
|
||||
}
|
||||
|
||||
// If the result of IsWellFormedUnitIdentifier(unit) is false, throw a
|
||||
// RangeError exception.
|
||||
Maybe<std::pair<icu::MeasureUnit, icu::MeasureUnit>> maybe_wellformed =
|
||||
IsWellFormedUnitIdentifier(isolate, unit);
|
||||
if (maybe_wellformed.IsNothing()) {
|
||||
THROW_NEW_ERROR(
|
||||
isolate,
|
||||
NewRangeError(
|
||||
MessageTemplate::kInvalidUnit,
|
||||
factory->NewStringFromStaticChars("Intl.NumberFormat"),
|
||||
factory->NewStringFromAsciiChecked(unit.c_str())),
|
||||
JSNumberFormat);
|
||||
}
|
||||
std::pair<icu::MeasureUnit, icu::MeasureUnit> unit_pair =
|
||||
maybe_wellformed.FromJust();
|
||||
|
||||
// Set intlObj.[[Unit]] to unit.
|
||||
if (unit_pair.first != icu::NoUnit::base()) {
|
||||
icu_number_formatter = icu_number_formatter.unit(unit_pair.first);
|
||||
}
|
||||
if (unit_pair.second != icu::NoUnit::base()) {
|
||||
icu_number_formatter = icu_number_formatter.perUnit(unit_pair.second);
|
||||
}
|
||||
|
||||
// The default unitWidth is SHORT in ICU and that mapped from
|
||||
// Symbol so we can skip the setting for optimization.
|
||||
if (unit_display != UnitDisplay::SHORT) {
|
||||
icu_number_formatter =
|
||||
icu_number_formatter.unitWidth(ToUNumberUnitWidth(unit_display));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
icu::number::LocalizedNumberFormatter icu_number_formatter =
|
||||
icu::number::NumberFormatter::withLocale(r.icu_locale)
|
||||
.roundingMode(UNUM_ROUND_HALFUP);
|
||||
if (style == Style::PERCENT) {
|
||||
icu_number_formatter = icu_number_formatter.unit(icu::NoUnit::percent())
|
||||
.scale(icu::number::Scale::powerOfTen(2));
|
||||
@ -670,6 +1162,35 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
digit_options.minimum_integer_digits));
|
||||
}
|
||||
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
// Let notation be ? GetOption(options, "notation", "string", « "standard",
|
||||
// "scientific", "engineering", "compact" », "standard").
|
||||
Maybe<Notation> maybe_notation = Intl::GetStringOption<Notation>(
|
||||
isolate, options, "notation", service,
|
||||
{"standard", "scientific", "engineering", "compact"},
|
||||
{Notation::STANDARD, Notation::SCIENTIFIC, Notation::ENGINEERING,
|
||||
Notation::COMPACT},
|
||||
Notation::STANDARD);
|
||||
MAYBE_RETURN(maybe_notation, MaybeHandle<JSNumberFormat>());
|
||||
Notation notation = maybe_notation.FromJust();
|
||||
|
||||
// Let compactDisplay be ? GetOption(options, "compactDisplay", "string", «
|
||||
// "short", "long" », "short").
|
||||
Maybe<CompactDisplay> maybe_compact_display =
|
||||
Intl::GetStringOption<CompactDisplay>(
|
||||
isolate, options, "compactDisplay", service, {"short", "long"},
|
||||
{CompactDisplay::SHORT, CompactDisplay::LONG},
|
||||
CompactDisplay::SHORT);
|
||||
MAYBE_RETURN(maybe_compact_display, MaybeHandle<JSNumberFormat>());
|
||||
CompactDisplay compact_display = maybe_compact_display.FromJust();
|
||||
|
||||
// The default notation in ICU is Simple, which mapped from STANDARD
|
||||
// so we can skip setting it.
|
||||
if (notation != Notation::STANDARD) {
|
||||
icu_number_formatter = icu_number_formatter.notation(
|
||||
ToICUNotation(notation, compact_display));
|
||||
}
|
||||
}
|
||||
// 23. Let useGrouping be ? GetOption(options, "useGrouping", "boolean",
|
||||
// undefined, true).
|
||||
bool use_grouping = true;
|
||||
@ -682,6 +1203,28 @@ MaybeHandle<JSNumberFormat> JSNumberFormat::Initialize(
|
||||
UNumberGroupingStrategy::UNUM_GROUPING_OFF);
|
||||
}
|
||||
|
||||
if (FLAG_harmony_intl_numberformat_unified) {
|
||||
// Let signDisplay be ? GetOption(options, "signDisplay", "string", «
|
||||
// "auto", "never", "always", "except-zero" », "auto").
|
||||
Maybe<SignDisplay> maybe_sign_display = Intl::GetStringOption<SignDisplay>(
|
||||
isolate, options, "signDisplay", service,
|
||||
{"auto", "never", "always", "except-zero"},
|
||||
{SignDisplay::AUTO, SignDisplay::NEVER, SignDisplay::ALWAYS,
|
||||
SignDisplay::EXCEPT_ZERO},
|
||||
SignDisplay::AUTO);
|
||||
MAYBE_RETURN(maybe_sign_display, MaybeHandle<JSNumberFormat>());
|
||||
SignDisplay sign_display = maybe_sign_display.FromJust();
|
||||
|
||||
// The default sign in ICU is UNUM_SIGN_AUTO which is mapped from
|
||||
// SignDisplay::AUTO and CurrencySign::STANDARD so we can skip setting
|
||||
// under that values for optimization.
|
||||
if (sign_display != SignDisplay::AUTO ||
|
||||
currency_sign != CurrencySign::STANDARD) {
|
||||
icu_number_formatter = icu_number_formatter.sign(
|
||||
ToUNumberSignDisplay(sign_display, currency_sign));
|
||||
}
|
||||
}
|
||||
|
||||
// 25. Let dataLocaleData be localeData.[[<dataLocale>]].
|
||||
//
|
||||
// 26. Let patterns be dataLocaleData.[[patterns]].
|
||||
@ -728,6 +1271,13 @@ Maybe<icu::UnicodeString> IcuFormatNumber(
|
||||
double number = numeric_obj->Number();
|
||||
formatted = number_format.formatDouble(number, status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
// This happen because of icu data trimming trim out "unit".
|
||||
// See https://bugs.chromium.org/p/v8/issues/detail?id=8641
|
||||
THROW_NEW_ERROR_RETURN_VALUE(isolate,
|
||||
NewTypeError(MessageTemplate::kIcuError),
|
||||
Nothing<icu::UnicodeString>());
|
||||
}
|
||||
if (fp_iter) {
|
||||
formatted.getAllFieldPositions(*fp_iter, status);
|
||||
}
|
||||
|
15
test/intl/number-format/unified/compact-display.js
Normal file
15
test/intl/number-format/unified/compact-display.js
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
const testData = [
|
||||
["short"],
|
||||
["long"],
|
||||
];
|
||||
|
||||
for (const [compactDisplay] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {compactDisplay, notation: "compact"});
|
||||
assertEquals(compactDisplay, nf.resolvedOptions().compactDisplay);
|
||||
}
|
70
test/intl/number-format/unified/constructor-order.js
Normal file
70
test/intl/number-format/unified/constructor-order.js
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
// Similar to constructor-order.js but also consider the new options
|
||||
// in https://tc39-transfer.github.io/proposal-unified-intl-numberformat/
|
||||
|
||||
// Throws only once during construction.
|
||||
// Check for all getters to prevent regression.
|
||||
// Preserve the order of getter initialization.
|
||||
let getCount = 0;
|
||||
|
||||
new Intl.NumberFormat(['en-US'], {
|
||||
get localeMatcher() {
|
||||
assertEquals(0, getCount++);
|
||||
},
|
||||
get style() {
|
||||
assertEquals(1, getCount++);
|
||||
},
|
||||
get currency() {
|
||||
assertEquals(2, getCount++);
|
||||
},
|
||||
get currencyDisplay() {
|
||||
assertEquals(3, getCount++);
|
||||
},
|
||||
// Begin of new options
|
||||
get currencySign() {
|
||||
assertEquals(4, getCount++);
|
||||
},
|
||||
get unit() {
|
||||
assertEquals(5, getCount++);
|
||||
},
|
||||
get unitDisplay() {
|
||||
assertEquals(6, getCount++);
|
||||
},
|
||||
// End of new options
|
||||
get minimumIntegerDigits() {
|
||||
assertEquals(7, getCount++);
|
||||
},
|
||||
get minimumFractionDigits() {
|
||||
assertEquals(8, getCount++);
|
||||
},
|
||||
get maximumFractionDigits() {
|
||||
assertEquals(9, getCount++);
|
||||
},
|
||||
get minimumSignificantDigits() {
|
||||
assertEquals(10, getCount++);
|
||||
},
|
||||
get maximumSignificantDigits() {
|
||||
assertEquals(11, getCount++);
|
||||
},
|
||||
// Begin of new options
|
||||
get notation() {
|
||||
assertEquals(12, getCount++);
|
||||
},
|
||||
get compactDisplay() {
|
||||
assertEquals(13, getCount++);
|
||||
},
|
||||
// End of new options
|
||||
get useGrouping() {
|
||||
assertEquals(14, getCount++);
|
||||
},
|
||||
// Begin of new options
|
||||
get signDisplay() {
|
||||
assertEquals(15, getCount++);
|
||||
},
|
||||
// End of new options
|
||||
});
|
||||
assertEquals(16, getCount);
|
39
test/intl/number-format/unified/currency-display.js
Normal file
39
test/intl/number-format/unified/currency-display.js
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test defaults
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals(undefined, nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals(undefined, nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: "decimal"});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: "percent"});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: "unit", unit: "meter"});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: "currency", currency: "TWD"});
|
||||
assertEquals("symbol", nf.resolvedOptions().currencyDisplay);
|
||||
|
||||
const testData = [
|
||||
["name", "123.00 New Taiwan dollars"],
|
||||
["code", "TWD 123.00"],
|
||||
["symbol", "NT$123.00"],
|
||||
["narrow-symbol", "$123.00"], // new
|
||||
];
|
||||
|
||||
for (const [currencyDisplay, expectation] of testData) {
|
||||
nf = new Intl.NumberFormat("en",
|
||||
{style: 'currency', currency: "TWD", currencyDisplay});
|
||||
assertEquals('currency', nf.resolvedOptions().style);
|
||||
assertEquals(currencyDisplay, nf.resolvedOptions().currencyDisplay);
|
||||
assertEquals(expectation, nf.format(123));
|
||||
}
|
41
test/intl/number-format/unified/currency-sign.js
Normal file
41
test/intl/number-format/unified/currency-sign.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test default.
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals(undefined, nf.resolvedOptions().currencySign);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals(undefined, nf.resolvedOptions().currencySign);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'decimal'});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencySign);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'percent'});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencySign);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'unit', unit: "meter"});
|
||||
assertEquals(undefined, nf.resolvedOptions().currencySign);
|
||||
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'currency', currency: "TWD"});
|
||||
assertEquals("standard", nf.resolvedOptions().currencySign);
|
||||
|
||||
const testData = [
|
||||
["standard", "-NT$123.40", "-NT$0.00", "NT$0.00", "NT$123.40"],
|
||||
["accounting", "(NT$123.40)", "(NT$0.00)", "NT$0.00", "NT$123.40"],
|
||||
];
|
||||
|
||||
for (const [currencySign, neg, negZero, zero, pos] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {style: 'currency', currency: "TWD",
|
||||
currencySign});
|
||||
assertEquals('currency', nf.resolvedOptions().style);
|
||||
assertEquals(currencySign, nf.resolvedOptions().currencySign);
|
||||
assertEquals(neg, nf.format(-123.4));
|
||||
assertEquals(negZero, nf.format(-0));
|
||||
assertEquals(zero, nf.format(0));
|
||||
assertEquals(pos, nf.format(123.4));
|
||||
}
|
30
test/intl/number-format/unified/no-compact-display.js
Normal file
30
test/intl/number-format/unified/no-compact-display.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Except when the notation is "compact", the resolvedOptions().compactDisplay
|
||||
// should be undefined.
|
||||
//
|
||||
// Test default
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals(undefined, nf.resolvedOptions().compactDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals(undefined, nf.resolvedOptions().compactDisplay);
|
||||
|
||||
const testData = [
|
||||
["scientific"],
|
||||
["engineering"],
|
||||
["standard"],
|
||||
];
|
||||
|
||||
for (const [notation] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {notation});
|
||||
assertEquals(undefined, nf.resolvedOptions().compactDisplay);
|
||||
for (const compactDisplay of ["short", "long"]) {
|
||||
nf = new Intl.NumberFormat("en", {compactDisplay, notation});
|
||||
assertEquals(undefined, nf.resolvedOptions().compactDisplay);
|
||||
}
|
||||
}
|
89
test/intl/number-format/unified/notation.js
Normal file
89
test/intl/number-format/unified/notation.js
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test defaults.
|
||||
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals("standard", nf.resolvedOptions().notation);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals("standard", nf.resolvedOptions().notation);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: "percent"});
|
||||
assertEquals("standard", nf.resolvedOptions().notation);
|
||||
|
||||
const testData = [
|
||||
["standard", undefined, "987,654,321"],
|
||||
["scientific", undefined, "9.877E8"],
|
||||
["engineering", undefined, "987.654E6"],
|
||||
["compact", undefined, "987.654M"],
|
||||
["compact", "short", "987.654M"],
|
||||
["compact", "long", "987.654 million"],
|
||||
];
|
||||
|
||||
for (const [notation, compactDisplay, expect1] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {notation, compactDisplay});
|
||||
assertEquals(notation, nf.resolvedOptions().notation);
|
||||
if (notation != "compact") {
|
||||
assertEquals(undefined, nf.resolvedOptions().compactDisplay);
|
||||
} else if (compactDisplay == "long") {
|
||||
assertEquals("long", nf.resolvedOptions().compactDisplay);
|
||||
} else {
|
||||
assertEquals("short", nf.resolvedOptions().compactDisplay);
|
||||
}
|
||||
assertEquals(expect1, nf.format(987654321));
|
||||
}
|
||||
|
||||
// Test Germany which has different decimal marks.
|
||||
let notation = "compact";
|
||||
nf = new Intl.NumberFormat("de", {notation, compactDisplay: "short"});
|
||||
assertEquals("987,654 Mio.", nf.format(987654321));
|
||||
assertEquals("98,765 Mio.", nf.format(98765432));
|
||||
assertEquals("98.765", nf.format(98765));
|
||||
assertEquals("9876", nf.format(9876));
|
||||
nf = new Intl.NumberFormat("de", {notation, compactDisplay: "long"});
|
||||
assertEquals("987,654 Millionen", nf.format(987654321));
|
||||
assertEquals("98,765 Millionen", nf.format(98765432));
|
||||
assertEquals("98,765 Tausend", nf.format(98765));
|
||||
assertEquals("9,876 Tausend", nf.format(9876));
|
||||
|
||||
// Test Chinese, Japanese and Korean, which group by 4 digits.
|
||||
nf = new Intl.NumberFormat("zh-TW", {notation, compactDisplay: "short"});
|
||||
assertEquals("9.877億", nf.format(987654321));
|
||||
assertEquals("9876.543萬", nf.format(98765432));
|
||||
assertEquals("9.877萬", nf.format(98765));
|
||||
assertEquals("9876", nf.format(9876));
|
||||
nf = new Intl.NumberFormat("zh-TW", {notation, compactDisplay: "long"});
|
||||
assertEquals("9.877億", nf.format(987654321));
|
||||
assertEquals("9876.543萬", nf.format(98765432));
|
||||
assertEquals("9.877萬", nf.format(98765));
|
||||
assertEquals("9876", nf.format(9876));
|
||||
|
||||
// Test Japanese with compact.
|
||||
nf = new Intl.NumberFormat("ja", {notation, compactDisplay: "short"});
|
||||
assertEquals("9.877億", nf.format(987654321));
|
||||
assertEquals("9876.543万", nf.format(98765432));
|
||||
assertEquals("9.877万", nf.format(98765));
|
||||
assertEquals("9876", nf.format(9876));
|
||||
nf = new Intl.NumberFormat("ja", {notation, compactDisplay: "long"});
|
||||
assertEquals("9.877億", nf.format(987654321));
|
||||
assertEquals("9876.543万", nf.format(98765432));
|
||||
assertEquals("9.877万", nf.format(98765));
|
||||
assertEquals("9876", nf.format(9876));
|
||||
|
||||
// Test Korean with compact.
|
||||
nf = new Intl.NumberFormat("ko", {notation, compactDisplay: "short"});
|
||||
assertEquals("9.877억", nf.format(987654321));
|
||||
assertEquals("9876.543만", nf.format(98765432));
|
||||
assertEquals("9.877만", nf.format(98765));
|
||||
assertEquals("9.876천", nf.format(9876));
|
||||
assertEquals("987", nf.format(987));
|
||||
nf = new Intl.NumberFormat("ko", {notation, compactDisplay: "long"});
|
||||
assertEquals("9.877억", nf.format(987654321));
|
||||
assertEquals("9876.543만", nf.format(98765432));
|
||||
assertEquals("9.877만", nf.format(98765));
|
||||
assertEquals("9.876천", nf.format(9876));
|
||||
assertEquals("987", nf.format(987));
|
28
test/intl/number-format/unified/sign-display.js
Normal file
28
test/intl/number-format/unified/sign-display.js
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test default.
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals("auto", nf.resolvedOptions().signDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals("auto", nf.resolvedOptions().signDisplay);
|
||||
|
||||
const testData = [
|
||||
["auto", "-123", "-0", "0", "123"],
|
||||
["always", "-123", "-0", "+0", "+123"],
|
||||
["never", "123", "0", "0", "123"],
|
||||
["except-zero", "-123", "-0", "0", "+123"],
|
||||
];
|
||||
|
||||
for (const [signDisplay, neg, negZero, zero, pos] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {signDisplay});
|
||||
assertEquals(signDisplay, nf.resolvedOptions().signDisplay);
|
||||
assertEquals(neg, nf.format(-123));
|
||||
assertEquals(negZero, nf.format(-0));
|
||||
assertEquals(zero, nf.format(0));
|
||||
assertEquals(pos, nf.format(123));
|
||||
}
|
180
test/intl/number-format/unified/style-unit.js
Normal file
180
test/intl/number-format/unified/style-unit.js
Normal file
@ -0,0 +1,180 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test default.
|
||||
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals(undefined, nf.resolvedOptions().unit);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals(undefined, nf.resolvedOptions().unit);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'decimal'});
|
||||
assertEquals(undefined, nf.resolvedOptions().unit);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'currency', currency: 'TWD'});
|
||||
assertEquals(undefined, nf.resolvedOptions().unit);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'percent'});
|
||||
assertEquals('percent', nf.resolvedOptions().unit);
|
||||
|
||||
assertThrows(() => new Intl.NumberFormat("en", {style: 'unit'}), TypeError);
|
||||
|
||||
const validUnits = [
|
||||
'acre',
|
||||
'bit',
|
||||
'byte',
|
||||
'celsius',
|
||||
'centimeter',
|
||||
'day',
|
||||
'degree',
|
||||
'fahrenheit',
|
||||
'foot',
|
||||
'gigabit',
|
||||
'gigabyte',
|
||||
'gram',
|
||||
'hectare',
|
||||
'hour',
|
||||
'inch',
|
||||
'kilobit',
|
||||
'kilobyte',
|
||||
'kilogram',
|
||||
'kilometer',
|
||||
'megabit',
|
||||
'megabyte',
|
||||
'meter',
|
||||
'mile-scandinavian',
|
||||
'mile',
|
||||
'millimeter',
|
||||
'millisecond',
|
||||
'minute',
|
||||
'month',
|
||||
'ounce',
|
||||
'petabyte',
|
||||
'pound',
|
||||
'second',
|
||||
'stone',
|
||||
'terabit',
|
||||
'terabyte',
|
||||
'week',
|
||||
'yard',
|
||||
'year',
|
||||
'percent',
|
||||
'kilometer-per-hour',
|
||||
'mile-per-hour',
|
||||
'meter-per-second',
|
||||
'yard-per-second',
|
||||
'yard-per-hour',
|
||||
];
|
||||
|
||||
for (const unit of validUnits) {
|
||||
let resolved = new Intl.NumberFormat(
|
||||
"en", {style: 'unit', unit}).resolvedOptions();
|
||||
assertEquals('unit', resolved.style);
|
||||
assertEquals(resolved.unit, unit);
|
||||
}
|
||||
|
||||
function c(u) {
|
||||
return new Intl.NumberFormat('en', { style: 'unit', unit: u});
|
||||
}
|
||||
assertThrows(() => c('acre-foot'), RangeError);
|
||||
assertThrows(() => c('ampere'), RangeError);
|
||||
assertThrows(() => c('arc-minute'), RangeError);
|
||||
assertThrows(() => c('arc-second'), RangeError);
|
||||
assertThrows(() => c('astronomical-unit'), RangeError);
|
||||
assertThrows(() => c('bushel'), RangeError);
|
||||
assertThrows(() => c('calorie'), RangeError);
|
||||
assertThrows(() => c('carat'), RangeError);
|
||||
assertThrows(() => c('centiliter'), RangeError);
|
||||
assertThrows(() => c('century'), RangeError);
|
||||
assertThrows(() => c('cubic-centimeter'), RangeError);
|
||||
assertThrows(() => c('cubic-foot'), RangeError);
|
||||
assertThrows(() => c('cubic-inch'), RangeError);
|
||||
assertThrows(() => c('cubic-kilometer'), RangeError);
|
||||
assertThrows(() => c('cubic-meter'), RangeError);
|
||||
assertThrows(() => c('cubic-mile'), RangeError);
|
||||
assertThrows(() => c('cubic-yard'), RangeError);
|
||||
assertThrows(() => c('cup-metric'), RangeError);
|
||||
assertThrows(() => c('cup'), RangeError);
|
||||
assertThrows(() => c('day-person'), RangeError);
|
||||
assertThrows(() => c('deciliter'), RangeError);
|
||||
assertThrows(() => c('decimeter'), RangeError);
|
||||
assertThrows(() => c('fathom'), RangeError);
|
||||
assertThrows(() => c('fluid-ounce'), RangeError);
|
||||
assertThrows(() => c('foodcalorie'), RangeError);
|
||||
assertThrows(() => c('furlong'), RangeError);
|
||||
assertThrows(() => c('g-force'), RangeError);
|
||||
assertThrows(() => c('gallon-imperial'), RangeError);
|
||||
assertThrows(() => c('gallon'), RangeError);
|
||||
assertThrows(() => c('generic'), RangeError);
|
||||
assertThrows(() => c('gigahertz'), RangeError);
|
||||
assertThrows(() => c('gigawatt'), RangeError);
|
||||
assertThrows(() => c('hectoliter'), RangeError);
|
||||
assertThrows(() => c('hectopascal'), RangeError);
|
||||
assertThrows(() => c('hertz'), RangeError);
|
||||
assertThrows(() => c('horsepower'), RangeError);
|
||||
assertThrows(() => c('inch-hg'), RangeError);
|
||||
assertThrows(() => c('joule'), RangeError);
|
||||
assertThrows(() => c('karat'), RangeError);
|
||||
assertThrows(() => c('kelvin'), RangeError);
|
||||
assertThrows(() => c('kilocalorie'), RangeError);
|
||||
assertThrows(() => c('kilohertz'), RangeError);
|
||||
assertThrows(() => c('kilojoule'), RangeError);
|
||||
assertThrows(() => c('kilowatt-hour'), RangeError);
|
||||
assertThrows(() => c('kilowatt'), RangeError);
|
||||
assertThrows(() => c('knot'), RangeError);
|
||||
assertThrows(() => c('light-year'), RangeError);
|
||||
assertThrows(() => c('liter-per-100kilometers'), RangeError);
|
||||
assertThrows(() => c('liter-per-kilometer'), RangeError);
|
||||
assertThrows(() => c('liter'), RangeError);
|
||||
assertThrows(() => c('lux'), RangeError);
|
||||
assertThrows(() => c('megahertz'), RangeError);
|
||||
assertThrows(() => c('megaliter'), RangeError);
|
||||
assertThrows(() => c('megawatt'), RangeError);
|
||||
assertThrows(() => c('meter-per-second-squared'), RangeError);
|
||||
assertThrows(() => c('metric-ton'), RangeError);
|
||||
assertThrows(() => c('microgram'), RangeError);
|
||||
assertThrows(() => c('micrometer'), RangeError);
|
||||
assertThrows(() => c('microsecond'), RangeError);
|
||||
assertThrows(() => c('mile-per-gallon-imperial'), RangeError);
|
||||
assertThrows(() => c('mile-per-gallon'), RangeError);
|
||||
assertThrows(() => c('milliampere'), RangeError);
|
||||
assertThrows(() => c('millibar'), RangeError);
|
||||
assertThrows(() => c('milligram-per-deciliter'), RangeError);
|
||||
assertThrows(() => c('milligram'), RangeError);
|
||||
assertThrows(() => c('milliliter'), RangeError);
|
||||
assertThrows(() => c('millimeter-of-mercury'), RangeError);
|
||||
assertThrows(() => c('millimole-per-liter'), RangeError);
|
||||
assertThrows(() => c('milliwatt'), RangeError);
|
||||
assertThrows(() => c('month-person'), RangeError);
|
||||
assertThrows(() => c('nanometer'), RangeError);
|
||||
assertThrows(() => c('nanosecond'), RangeError);
|
||||
assertThrows(() => c('nautical-mile'), RangeError);
|
||||
assertThrows(() => c('ohm'), RangeError);
|
||||
assertThrows(() => c('ounce-troy'), RangeError);
|
||||
assertThrows(() => c('parsec'), RangeError);
|
||||
assertThrows(() => c('part-per-million'), RangeError);
|
||||
assertThrows(() => c('picometer'), RangeError);
|
||||
assertThrows(() => c('pint-metric'), RangeError);
|
||||
assertThrows(() => c('pint'), RangeError);
|
||||
assertThrows(() => c('pound-per-square-inch'), RangeError);
|
||||
assertThrows(() => c('quart'), RangeError);
|
||||
assertThrows(() => c('radian'), RangeError);
|
||||
assertThrows(() => c('revolution'), RangeError);
|
||||
assertThrows(() => c('square-centimeter'), RangeError);
|
||||
assertThrows(() => c('square-foot'), RangeError);
|
||||
assertThrows(() => c('square-inch'), RangeError);
|
||||
assertThrows(() => c('square-kilometer'), RangeError);
|
||||
assertThrows(() => c('square-meter'), RangeError);
|
||||
assertThrows(() => c('square-mile'), RangeError);
|
||||
assertThrows(() => c('square-yard'), RangeError);
|
||||
assertThrows(() => c('tablespoon'), RangeError);
|
||||
assertThrows(() => c('teaspoon'), RangeError);
|
||||
assertThrows(() => c('ton'), RangeError);
|
||||
assertThrows(() => c('volt'), RangeError);
|
||||
assertThrows(() => c('watt'), RangeError);
|
||||
assertThrows(() => c('week-person'), RangeError);
|
||||
assertThrows(() => c('year-person'), RangeError);
|
36
test/intl/number-format/unified/unit-display.js
Normal file
36
test/intl/number-format/unified/unit-display.js
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-intl-numberformat-unified
|
||||
|
||||
// Test default.
|
||||
let nf = new Intl.NumberFormat();
|
||||
assertEquals(undefined, nf.resolvedOptions().unitDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en");
|
||||
assertEquals(undefined, nf.resolvedOptions().unitDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'decimal'});
|
||||
assertEquals(undefined, nf.resolvedOptions().unitDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'currency', currency: 'TWD'});
|
||||
assertEquals(undefined, nf.resolvedOptions().unitDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'unit', unit: "meter"});
|
||||
assertEquals("short", nf.resolvedOptions().unitDisplay);
|
||||
|
||||
nf = new Intl.NumberFormat("en", {style: 'percent'});
|
||||
assertEquals("short", nf.resolvedOptions().unitDisplay);
|
||||
|
||||
const testData = [
|
||||
["short"],
|
||||
["narrow"],
|
||||
["long"],
|
||||
];
|
||||
|
||||
for (const [unitDisplay] of testData) {
|
||||
nf = new Intl.NumberFormat("en", {style: 'unit', unit: "meter", unitDisplay});
|
||||
assertEquals('unit', nf.resolvedOptions().style);
|
||||
assertEquals(unitDisplay, nf.resolvedOptions().unitDisplay);
|
||||
}
|
@ -47,6 +47,7 @@ FEATURE_FLAGS = {
|
||||
'numeric-separator-literal': '--harmony-numeric-separator',
|
||||
'Intl.DateTimeFormat-datetimestyle': '--harmony-intl-datetime-style',
|
||||
'Intl.DateTimeFormat-formatRange': '--harmony-intl-date-format-range',
|
||||
'Intl.NumberFormat-unified': '--harmony-intl-numberformat-unified',
|
||||
'Intl.Segmenter': '--harmony-intl-segmenter',
|
||||
'Symbol.prototype.description': '--harmony-symbol-description',
|
||||
'globalThis': '--harmony-global',
|
||||
@ -58,8 +59,7 @@ FEATURE_FLAGS = {
|
||||
}
|
||||
|
||||
SKIPPED_FEATURES = set(['class-methods-private',
|
||||
'class-static-methods-private',
|
||||
'Intl.NumberFormat-unified'])
|
||||
'class-static-methods-private'])
|
||||
|
||||
DATA = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
|
||||
|
||||
|
@ -307,50 +307,50 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x014b1): (98, "EnumCacheMap"),
|
||||
("read_only_space", 0x01501): (116, "ArrayBoilerplateDescriptionMap"),
|
||||
("read_only_space", 0x016d9): (101, "InterceptorInfoMap"),
|
||||
("read_only_space", 0x0357d): (89, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x035a5): (90, "AccessorInfoMap"),
|
||||
("read_only_space", 0x035cd): (91, "AccessorPairMap"),
|
||||
("read_only_space", 0x035f5): (92, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x0361d): (93, "AllocationMementoMap"),
|
||||
("read_only_space", 0x03645): (94, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x0366d): (95, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x03695): (96, "ClassPositionsMap"),
|
||||
("read_only_space", 0x036bd): (97, "DebugInfoMap"),
|
||||
("read_only_space", 0x036e5): (99, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x0370d): (100, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x03735): (102, "InterpreterDataMap"),
|
||||
("read_only_space", 0x0375d): (103, "ModuleInfoEntryMap"),
|
||||
("read_only_space", 0x03785): (104, "ModuleMap"),
|
||||
("read_only_space", 0x037ad): (105, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x037d5): (106, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x037fd): (107, "PromiseReactionMap"),
|
||||
("read_only_space", 0x03825): (108, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x0384d): (109, "ScriptMap"),
|
||||
("read_only_space", 0x03875): (110, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x0389d): (111, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x038c5): (112, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x038ed): (113, "TemplateObjectDescriptionMap"),
|
||||
("read_only_space", 0x03915): (114, "Tuple2Map"),
|
||||
("read_only_space", 0x0393d): (115, "Tuple3Map"),
|
||||
("read_only_space", 0x03965): (117, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x0398d): (118, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x039b5): (119, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x039dd): (120, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x03a05): (121, "CallableTaskMap"),
|
||||
("read_only_space", 0x03a2d): (122, "CallbackTaskMap"),
|
||||
("read_only_space", 0x03a55): (123, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x03a7d): (124, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x03aa5): (125, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x03acd): (126, "FinalizationGroupCleanupJobTaskMap"),
|
||||
("read_only_space", 0x03af5): (127, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x03b1d): (127, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x03b45): (162, "LoadHandler1Map"),
|
||||
("read_only_space", 0x03b6d): (162, "LoadHandler2Map"),
|
||||
("read_only_space", 0x03b95): (162, "LoadHandler3Map"),
|
||||
("read_only_space", 0x03bbd): (170, "StoreHandler0Map"),
|
||||
("read_only_space", 0x03be5): (170, "StoreHandler1Map"),
|
||||
("read_only_space", 0x03c0d): (170, "StoreHandler2Map"),
|
||||
("read_only_space", 0x03c35): (170, "StoreHandler3Map"),
|
||||
("read_only_space", 0x035f5): (89, "AccessCheckInfoMap"),
|
||||
("read_only_space", 0x0361d): (90, "AccessorInfoMap"),
|
||||
("read_only_space", 0x03645): (91, "AccessorPairMap"),
|
||||
("read_only_space", 0x0366d): (92, "AliasedArgumentsEntryMap"),
|
||||
("read_only_space", 0x03695): (93, "AllocationMementoMap"),
|
||||
("read_only_space", 0x036bd): (94, "AsmWasmDataMap"),
|
||||
("read_only_space", 0x036e5): (95, "AsyncGeneratorRequestMap"),
|
||||
("read_only_space", 0x0370d): (96, "ClassPositionsMap"),
|
||||
("read_only_space", 0x03735): (97, "DebugInfoMap"),
|
||||
("read_only_space", 0x0375d): (99, "FunctionTemplateInfoMap"),
|
||||
("read_only_space", 0x03785): (100, "FunctionTemplateRareDataMap"),
|
||||
("read_only_space", 0x037ad): (102, "InterpreterDataMap"),
|
||||
("read_only_space", 0x037d5): (103, "ModuleInfoEntryMap"),
|
||||
("read_only_space", 0x037fd): (104, "ModuleMap"),
|
||||
("read_only_space", 0x03825): (105, "ObjectTemplateInfoMap"),
|
||||
("read_only_space", 0x0384d): (106, "PromiseCapabilityMap"),
|
||||
("read_only_space", 0x03875): (107, "PromiseReactionMap"),
|
||||
("read_only_space", 0x0389d): (108, "PrototypeInfoMap"),
|
||||
("read_only_space", 0x038c5): (109, "ScriptMap"),
|
||||
("read_only_space", 0x038ed): (110, "SourcePositionTableWithFrameCacheMap"),
|
||||
("read_only_space", 0x03915): (111, "StackFrameInfoMap"),
|
||||
("read_only_space", 0x0393d): (112, "StackTraceFrameMap"),
|
||||
("read_only_space", 0x03965): (113, "TemplateObjectDescriptionMap"),
|
||||
("read_only_space", 0x0398d): (114, "Tuple2Map"),
|
||||
("read_only_space", 0x039b5): (115, "Tuple3Map"),
|
||||
("read_only_space", 0x039dd): (117, "WasmCapiFunctionDataMap"),
|
||||
("read_only_space", 0x03a05): (118, "WasmDebugInfoMap"),
|
||||
("read_only_space", 0x03a2d): (119, "WasmExceptionTagMap"),
|
||||
("read_only_space", 0x03a55): (120, "WasmExportedFunctionDataMap"),
|
||||
("read_only_space", 0x03a7d): (121, "CallableTaskMap"),
|
||||
("read_only_space", 0x03aa5): (122, "CallbackTaskMap"),
|
||||
("read_only_space", 0x03acd): (123, "PromiseFulfillReactionJobTaskMap"),
|
||||
("read_only_space", 0x03af5): (124, "PromiseRejectReactionJobTaskMap"),
|
||||
("read_only_space", 0x03b1d): (125, "PromiseResolveThenableJobTaskMap"),
|
||||
("read_only_space", 0x03b45): (126, "FinalizationGroupCleanupJobTaskMap"),
|
||||
("read_only_space", 0x03b6d): (127, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x03b95): (127, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x03bbd): (162, "LoadHandler1Map"),
|
||||
("read_only_space", 0x03be5): (162, "LoadHandler2Map"),
|
||||
("read_only_space", 0x03c0d): (162, "LoadHandler3Map"),
|
||||
("read_only_space", 0x03c35): (170, "StoreHandler0Map"),
|
||||
("read_only_space", 0x03c5d): (170, "StoreHandler1Map"),
|
||||
("read_only_space", 0x03c85): (170, "StoreHandler2Map"),
|
||||
("read_only_space", 0x03cad): (170, "StoreHandler3Map"),
|
||||
("map_space", 0x00139): (1057, "ExternalMap"),
|
||||
("map_space", 0x00161): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user