6#error Internationalization is expected to be enabled.
22#pragma GCC diagnostic push
23#pragma GCC diagnostic ignored "-Wshadow"
24#include "unicode/currunit.h"
25#include "unicode/locid.h"
26#include "unicode/numberformatter.h"
27#include "unicode/numberrangeformatter.h"
28#include "unicode/numsys.h"
29#include "unicode/ucurr.h"
30#include "unicode/uloc.h"
31#include "unicode/unumberformatter.h"
32#include "unicode/uvernum.h"
33#pragma GCC diagnostic pop
42#define AVOID_AMBIGUOUS_OP_WARNING(x) *static_cast<icu::UObject*>(&x)
46enum class Style { DECIMAL, PERCENT, CURRENCY, UNIT };
50enum class CurrencyDisplay {
61enum class CurrencySign {
70enum class UnitDisplay {
95enum class CompactDisplay {
104enum class SignDisplay {
113enum class UseGrouping {
120UNumberUnitWidth ToUNumberUnitWidth(CurrencyDisplay currency_display) {
121 switch (currency_display) {
122 case CurrencyDisplay::SYMBOL:
123 return UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT;
124 case CurrencyDisplay::CODE:
125 return UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE;
126 case CurrencyDisplay::NAME:
127 return UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME;
128 case CurrencyDisplay::NARROW_SYMBOL:
129 return UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW;
133UNumberUnitWidth ToUNumberUnitWidth(UnitDisplay unit_display) {
134 switch (unit_display) {
135 case UnitDisplay::SHORT:
136 return UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT;
137 case UnitDisplay::LONG:
138 return UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME;
139 case UnitDisplay::NARROW:
140 return UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW;
144UNumberSignDisplay ToUNumberSignDisplay(SignDisplay sign_display,
145 CurrencySign currency_sign) {
146 switch (sign_display) {
147 case SignDisplay::AUTO:
148 if (currency_sign == CurrencySign::ACCOUNTING) {
149 return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING;
151 DCHECK(currency_sign == CurrencySign::STANDARD);
152 return UNumberSignDisplay::UNUM_SIGN_AUTO;
153 case SignDisplay::NEVER:
154 return UNumberSignDisplay::UNUM_SIGN_NEVER;
155 case SignDisplay::ALWAYS:
156 if (currency_sign == CurrencySign::ACCOUNTING) {
157 return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_ALWAYS;
159 DCHECK(currency_sign == CurrencySign::STANDARD);
160 return UNumberSignDisplay::UNUM_SIGN_ALWAYS;
161 case SignDisplay::EXCEPT_ZERO:
162 if (currency_sign == CurrencySign::ACCOUNTING) {
163 return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
165 DCHECK(currency_sign == CurrencySign::STANDARD);
166 return UNumberSignDisplay::UNUM_SIGN_EXCEPT_ZERO;
167 case SignDisplay::NEGATIVE:
168 if (currency_sign == CurrencySign::ACCOUNTING) {
169 return UNumberSignDisplay::UNUM_SIGN_ACCOUNTING_NEGATIVE;
171 DCHECK(currency_sign == CurrencySign::STANDARD);
172 return UNumberSignDisplay::UNUM_SIGN_NEGATIVE;
176icu::number::Notation ToICUNotation(Notation notation,
177 CompactDisplay compact_display) {
179 case Notation::STANDARD:
180 return icu::number::Notation::simple();
181 case Notation::SCIENTIFIC:
182 return icu::number::Notation::scientific();
183 case Notation::ENGINEERING:
184 return icu::number::Notation::engineering();
186 case Notation::COMPACT:
188 if (compact_display == CompactDisplay::SHORT) {
189 return icu::number::Notation::compactShort();
191 DCHECK(compact_display == CompactDisplay::LONG);
192 return icu::number::Notation::compactLong();
196UNumberFormatRoundingMode ToUNumberFormatRoundingMode(
200 return UNumberFormatRoundingMode::UNUM_ROUND_CEILING;
202 return UNumberFormatRoundingMode::UNUM_ROUND_FLOOR;
204 return UNumberFormatRoundingMode::UNUM_ROUND_UP;
206 return UNumberFormatRoundingMode::UNUM_ROUND_DOWN;
208 return UNumberFormatRoundingMode::UNUM_ROUND_HALF_CEILING;
210 return UNumberFormatRoundingMode::UNUM_ROUND_HALF_FLOOR;
212 return UNumberFormatRoundingMode::UNUM_ROUND_HALFUP;
214 return UNumberFormatRoundingMode::UNUM_ROUND_HALFDOWN;
216 return UNumberFormatRoundingMode::UNUM_ROUND_HALFEVEN;
220UNumberGroupingStrategy ToUNumberGroupingStrategy(UseGrouping use_grouping) {
221 switch (use_grouping) {
222 case UseGrouping::OFF:
223 return UNumberGroupingStrategy::UNUM_GROUPING_OFF;
224 case UseGrouping::MIN2:
225 return UNumberGroupingStrategy::UNUM_GROUPING_MIN2;
226 case UseGrouping::AUTO:
227 return UNumberGroupingStrategy::UNUM_GROUPING_AUTO;
228 case UseGrouping::ALWAYS:
229 return UNumberGroupingStrategy::UNUM_GROUPING_ON_ALIGNED;
233std::map<const std::string, icu::MeasureUnit> CreateUnitMap() {
234 UErrorCode status = U_ZERO_ERROR;
235 int32_t total = icu::MeasureUnit::getAvailable(
nullptr, 0, status);
236 DCHECK(U_FAILURE(status));
237 status = U_ZERO_ERROR;
238 std::vector<icu::MeasureUnit>
units(total);
239 total = icu::MeasureUnit::getAvailable(
units.data(), total, status);
240 DCHECK(U_SUCCESS(status));
241 std::map<const std::string, icu::MeasureUnit>
map;
243 for (
auto it =
units.begin(); it !=
units.end(); ++it) {
245 if (sanctioned.count(it->getSubtype()) > 0 &&
246 strcmp(
"none", it->getType()) != 0) {
247 map[it->getSubtype()] = *it;
255 UnitFactory() :
map_(CreateUnitMap()) {}
256 virtual ~UnitFactory() =
default;
259 icu::MeasureUnit create(
const std::string& unitIdentifier) {
261 auto found =
map_.find(unitIdentifier);
262 if (found !=
map_.end()) {
263 return found->second;
266 return icu::MeasureUnit();
270 std::map<const std::string, icu::MeasureUnit>
map_;
274icu::MeasureUnit IsSanctionedUnitIdentifier(
const std::string&
unit) {
277 return factory.Pointer()->create(
unit);
281Maybe<std::pair<icu::MeasureUnit, icu::MeasureUnit>> IsWellFormedUnitIdentifier(
282 Isolate* isolate,
const std::string&
unit) {
283 icu::MeasureUnit
result = IsSanctionedUnitIdentifier(
unit);
284 icu::MeasureUnit
none = icu::MeasureUnit();
289 std::pair<icu::MeasureUnit, icu::MeasureUnit> pair(
result,
none);
294 size_t first_per =
unit.find(
"-per-");
295 if (first_per == std::string::npos ||
296 unit.find(
"-per-", first_per + 5) != std::string::npos) {
302 std::string numerator =
unit.substr(0, first_per);
305 result = IsSanctionedUnitIdentifier(numerator);
312 std::string denominator =
unit.substr(first_per + 5);
315 icu::MeasureUnit den_result = IsSanctionedUnitIdentifier(denominator);
321 std::pair<icu::MeasureUnit, icu::MeasureUnit> pair(
result, den_result);
327int CurrencyDigits(
const icu::UnicodeString& currency) {
328 UErrorCode status = U_ZERO_ERROR;
329 uint32_t fraction_digits = ucurr_getDefaultFractionDigits(
330 reinterpret_cast<const UChar*
>(currency.getBuffer()), &status);
332 return U_SUCCESS(status) ? fraction_digits : 2;
335bool IsAToZ(
char ch) {
340bool IsWellFormedCurrencyCode(
const std::string& currency) {
344 if (currency.length() != 3)
return false;
354 return (IsAToZ(currency[0]) && IsAToZ(currency[1]) && IsAToZ(currency[2]));
358DirectHandle<String> StyleAsString(Isolate* isolate, Style
style) {
361 return isolate->factory()->percent_string();
362 case Style::CURRENCY:
363 return isolate->factory()->currency_string();
365 return isolate->factory()->unit_string();
367 return isolate->factory()->decimal_string();
373DirectHandle<String> CurrencyDisplayString(Isolate* isolate,
374 const icu::UnicodeString& skeleton) {
377 if (skeleton.indexOf(
"unit-width-iso-code") >= 0) {
378 return isolate->factory()->code_string();
382 if (skeleton.indexOf(
"unit-width-full-name") >= 0) {
383 return isolate->factory()->name_string();
387 if (skeleton.indexOf(
"unit-width-narrow") >= 0) {
388 return isolate->factory()->narrowSymbol_string();
391 return isolate->factory()->symbol_string();
394DirectHandle<Object> UseGroupingFromSkeleton(
395 Isolate* isolate,
const icu::UnicodeString& skeleton) {
396 Factory* factory = isolate->factory();
397 static const char* group =
"group-";
401 icu::UnicodeString check = skeleton.tempSubString(
start + 6);
404 if (check.startsWith(
"off")) {
405 return factory->false_value();
409 if (check.startsWith(
"min2")) {
410 return isolate->factory()->min2_string();
414 if (check.startsWith(
"on-aligned")) {
415 return isolate->factory()->always_string();
420 return isolate->factory()->auto_string();
425const icu::UnicodeString CurrencyFromSkeleton(
426 const icu::UnicodeString& skeleton) {
427 const char currency[] =
"currency/";
428 int32_t index = skeleton.indexOf(currency);
429 if (index < 0)
return "";
430 index +=
static_cast<int32_t>(std::strlen(currency));
431 return skeleton.tempSubString(index, 3);
436 const icu::UnicodeString& skeleton) {
437 const char numbering_system[] =
"numbering-system/";
438 int32_t index = skeleton.indexOf(numbering_system);
439 if (index < 0)
return "latn";
440 index +=
static_cast<int32_t
>(std::strlen(numbering_system));
441 const icu::UnicodeString res = skeleton.tempSubString(index);
442 index = res.indexOf(
" ");
443 if (index < 0)
return res;
444 return res.tempSubString(0, index);
451 const icu::UnicodeString& skeleton) {
455 if (skeleton.indexOf(
"sign-accounting") >= 0) {
456 return isolate->factory()->accounting_string();
458 return isolate->factory()->standard_string();
462DirectHandle<String> UnitDisplayString(Isolate* isolate,
463 const icu::UnicodeString& skeleton) {
466 if (skeleton.indexOf(
"unit-width-full-name") >= 0) {
467 return isolate->factory()->long_string();
471 if (skeleton.indexOf(
"unit-width-narrow") >= 0) {
472 return isolate->factory()->narrow_string();
476 return isolate->factory()->short_string();
480Notation NotationFromSkeleton(
const icu::UnicodeString& skeleton) {
483 if (skeleton.indexOf(
"scientific") >= 0) {
484 return Notation::SCIENTIFIC;
488 if (skeleton.indexOf(
"engineering") >= 0) {
489 return Notation::ENGINEERING;
494 if (skeleton.indexOf(
"compact-") >= 0) {
495 return Notation::COMPACT;
499 return Notation::STANDARD;
502DirectHandle<String> NotationAsString(Isolate* isolate, Notation notation) {
504 case Notation::SCIENTIFIC:
505 return isolate->factory()->scientific_string();
506 case Notation::ENGINEERING:
507 return isolate->factory()->engineering_string();
508 case Notation::COMPACT:
509 return isolate->factory()->compact_string();
510 case Notation::STANDARD:
511 return isolate->factory()->standard_string();
517DirectHandle<String> CompactDisplayString(Isolate* isolate,
518 const icu::UnicodeString& skeleton) {
521 if (skeleton.indexOf(
"compact-long") >= 0) {
522 return isolate->factory()->long_string();
526 DCHECK_GE(skeleton.indexOf(
"compact-short"), 0);
527 return isolate->factory()->short_string();
531DirectHandle<String> SignDisplayString(Isolate* isolate,
532 const icu::UnicodeString& skeleton) {
535 if (skeleton.indexOf(
"sign-never") >= 0) {
536 return isolate->factory()->never_string();
541 if (skeleton.indexOf(
"sign-always") >= 0 ||
542 skeleton.indexOf(
"sign-accounting-always") >= 0) {
543 return isolate->factory()->always_string();
548 if (skeleton.indexOf(
"sign-accounting-except-zero") >= 0 ||
549 skeleton.indexOf(
"sign-except-zero") >= 0) {
550 return isolate->factory()->exceptZero_string();
555 if (skeleton.indexOf(
"sign-accounting-negative") >= 0 ||
556 skeleton.indexOf(
"sign-negative") >= 0) {
557 return isolate->factory()->negative_string();
559 return isolate->factory()->auto_string();
566 Isolate* isolate,
const icu::UnicodeString& skeleton) {
571 icu::UnicodeString check = skeleton.tempSubString(
start + 14);
575 if (check.startsWith(
"ceiling")) {
576 return isolate->factory()->ceil_string();
580 if (check.startsWith(
"down")) {
581 return isolate->factory()->trunc_string();
585 if (check.startsWith(
"floor")) {
586 return isolate->factory()->floor_string();
590 if (check.startsWith(
"half-ceiling")) {
591 return isolate->factory()->halfCeil_string();
595 if (check.startsWith(
"half-down")) {
596 return isolate->factory()->halfTrunc_string();
600 if (check.startsWith(
"half-floor")) {
601 return isolate->factory()->halfFloor_string();
605 if (check.startsWith(
"half-up")) {
606 return isolate->factory()->halfExpand_string();
610 if (check.startsWith(
"up")) {
611 return isolate->factory()->expand_string();
616 return isolate->factory()->halfEven_string();
620 Isolate* isolate,
const icu::UnicodeString& skeleton) {
621 int32_t cur = skeleton.indexOf(u
"precision-increment/");
622 if (cur < 0)
return isolate->factory()->NewNumberFromInt(1);
625 while (cur < skeleton.length()) {
626 char16_t c = skeleton[cur++];
627 if (c == u
'.')
continue;
631 return isolate->factory()->NewNumberFromInt(
increment);
636 Isolate* isolate,
const icu::UnicodeString& skeleton) {
639 if ((found = skeleton.indexOf(
"#r")) >= 0 ||
640 (found = skeleton.indexOf(
"@r")) >= 0) {
641 if (found + 2 == skeleton.length() || skeleton[found + 2] ==
' ') {
642 return isolate->factory()->morePrecision_string();
646 if ((found = skeleton.indexOf(
"#s")) >= 0 ||
647 (found = skeleton.indexOf(
"@s")) >= 0) {
648 if (found + 2 == skeleton.length() || skeleton[found + 2] ==
' ') {
649 return isolate->factory()->lessPrecision_string();
652 return isolate->factory()->auto_string();
657 Isolate* isolate,
const icu::UnicodeString& skeleton) {
659 if ((found = skeleton.indexOf(
"/w")) >= 0) {
660 if (found + 2 == skeleton.length() || skeleton[found + 2] ==
' ') {
661 return isolate->factory()->stripIfInteger_string();
664 return isolate->factory()->auto_string();
675 const icu::UnicodeString& skeleton) {
677 icu::UnicodeString search(
"integer-width/*");
678 int32_t index = skeleton.indexOf(search);
679 if (index < 0)
return 1;
680 index += search.length();
682 while (index < skeleton.length() && skeleton[index] ==
'0') {
706 const icu::UnicodeString& skeleton, int32_t* minimum, int32_t* maximum) {
707 int32_t index = skeleton.indexOf(
".");
714 if (skeleton.indexOf(
"precision-integer") >= 0 ||
715 skeleton.indexOf(
"precision-increment/") >= 0) {
716 *minimum = *maximum = 0;
723 while (index < skeleton.length() &&
IsDecimalDigit(skeleton[index])) {
728 while (index < skeleton.length() && skeleton[index] ==
'#') {
744 const icu::UnicodeString& skeleton, int32_t* minimum, int32_t* maximum) {
745 int32_t index = skeleton.indexOf(
"@");
746 if (index < 0)
return false;
749 while (index < skeleton.length() && skeleton[index] ==
'@') {
754 while (index < skeleton.length() && skeleton[index] ==
'#') {
769std::string UnitFromSkeleton(
const icu::UnicodeString& skeleton) {
771 str = skeleton.toUTF8String<std::string>(str);
772 std::string search(
"unit/");
773 size_t begin = str.find(search);
774 if (begin == str.npos) {
776 if (str.find(
"percent") != str.npos) {
787 begin += search.size();
788 if (begin == str.npos) {
792 size_t end = str.find(
' ', begin);
799 if (
end == str.npos) {
802 return str.substr(begin,
end - begin);
805Style StyleFromSkeleton(
const icu::UnicodeString& skeleton) {
806 if (skeleton.indexOf(
"currency/") >= 0) {
807 return Style::CURRENCY;
809 if (skeleton.indexOf(
"percent") >= 0) {
811 if (skeleton.indexOf(
"scale/100") >= 0) {
812 return Style::PERCENT;
818 if (skeleton.indexOf(
"unit/") >= 0) {
821 return Style::DECIMAL;
826icu::number::UnlocalizedNumberFormatter
828 const icu::number::UnlocalizedNumberFormatter& settings,
830 icu::number::UnlocalizedNumberFormatter
result = settings.roundingMode(
834 result =
result.integerWidth(icu::number::IntegerWidth::zeroFillTo(
838 icu::number::Precision
precision = icu::number::Precision::unlimited();
839 bool relaxed =
false;
842 precision = icu::number::Precision::minMaxSignificantDigits(
847 precision = icu::number::Precision::minMaxFraction(
856 icu::number::Precision::minMaxFraction(
861 relaxed ? UNUM_ROUNDING_PRIORITY_RELAXED
862 : UNUM_ROUNDING_PRIORITY_STRICT);
866 precision = ::icu::number::Precision::incrementExact(
882 Factory* factory = isolate->factory();
884 UErrorCode status = U_ZERO_ERROR;
885 icu::number::LocalizedNumberFormatter* fmt =
886 number_format->icu_number_formatter()->raw();
887 icu::UnicodeString skeleton = fmt->toSkeleton(status);
888 DCHECK(U_SUCCESS(status));
896 const icu::UnicodeString numberingSystem_ustr =
924 factory->locale_string(), locale,
929 .ToHandle(&numberingSystem_string));
931 factory->numberingSystem_string(),
934 Style
style = StyleFromSkeleton(skeleton);
936 isolate, options, factory->style_string(),
939 const icu::UnicodeString currency_ustr = CurrencyFromSkeleton(skeleton);
940 if (!currency_ustr.isEmpty()) {
944 factory->currency_string(),
949 isolate, options, factory->currencyDisplay_string(),
953 isolate, options, factory->currencySign_string(),
958 if (
style == Style::UNIT) {
959 std::string
unit = UnitFromSkeleton(skeleton);
962 isolate, options, factory->unit_string(),
968 isolate, options, factory->unitDisplay_string(),
975 isolate, options, factory->minimumIntegerDigits_string(),
980 int32_t mnsd = 0, mxsd = 0, mnfd = 0, mxfd = 0;
983 isolate, options, factory->minimumFractionDigits_string(),
987 isolate, options, factory->maximumFractionDigits_string(),
993 isolate, options, factory->minimumSignificantDigits_string(),
997 isolate, options, factory->maximumSignificantDigits_string(),
1003 isolate, options, factory->useGrouping_string(),
1007 Notation notation = NotationFromSkeleton(skeleton);
1009 isolate, options, factory->notation_string(),
1013 if (notation == Notation::COMPACT) {
1015 isolate, options, factory->compactDisplay_string(),
1020 isolate, options, factory->signDisplay_string(),
1024 isolate, options, factory->roundingIncrement_string(),
1028 isolate, options, factory->roundingMode_string(),
1032 isolate, options, factory->roundingPriority_string(),
1036 isolate, options, factory->trailingZeroDisplay_string(),
1055 IsJSNumberFormat(*format_holder)));
1058 if (!IsJSNumberFormat(*
object)) {
1061 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1062 isolate->factory()->NewStringFromAsciiChecked(
1063 "UnwrapNumberFormat")));
1073 Factory* factory = isolate->factory();
1079 std::vector<std::string> requested_locales =
1080 maybe_requested_locales.
FromJust();
1096 std::unique_ptr<char[]> numbering_system_str =
nullptr;
1100 isolate, options, service, &numbering_system_str);
1111 std::set<std::string> relevant_extension_keys{
"nu"};
1114 requested_locales, matcher, relevant_extension_keys);
1120 icu::Locale icu_locale =
r.icu_locale;
1121 UErrorCode status = U_ZERO_ERROR;
1122 if (numbering_system_str !=
nullptr) {
1123 auto nu_extension_it =
r.extensions.find(
"nu");
1124 if (nu_extension_it !=
r.extensions.end() &&
1125 nu_extension_it->second != numbering_system_str.get()) {
1126 icu_locale.setUnicodeKeywordValue(
"nu",
nullptr, status);
1127 DCHECK(U_SUCCESS(status));
1135 isolate->factory()->NewStringFromAsciiChecked(
1136 maybe_locale_str.
FromJust().c_str());
1138 if (numbering_system_str !=
nullptr &&
1140 icu_locale.setUnicodeKeywordValue(
"nu", numbering_system_str.get(), status);
1141 DCHECK(U_SUCCESS(status));
1148 icu::number::UnlocalizedNumberFormatter settings =
1149 icu::number::UnlocalizedNumberFormatter().roundingMode(UNUM_ROUND_HALFUP);
1155 if (!numbering_system.empty() && numbering_system !=
"latn") {
1156 settings = settings.adoptSymbols(icu::NumberingSystem::createInstanceByName(
1157 numbering_system.c_str(), status));
1158 DCHECK(U_SUCCESS(status));
1166 isolate, options,
"style", service,
1167 {
"decimal",
"percent",
"currency",
"unit"},
1168 {Style::DECIMAL, Style::PERCENT, Style::CURRENCY, Style::UNIT},
1177 std::unique_ptr<char[]> currency_cstr;
1178 const std::vector<const char*> empty_values = {};
1180 isolate, options,
"currency", empty_values, service, ¤cy_cstr);
1183 std::string currency;
1187 currency = currency_cstr.get();
1190 if (!IsWellFormedCurrencyCode(currency)) {
1193 NewRangeError(MessageTemplate::kInvalid,
1200 if (
style == Style::CURRENCY) {
1201 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCurrencyCode));
1208 isolate, options,
"currencyDisplay", service,
1209 {
"code",
"symbol",
"name",
"narrowSymbol"},
1210 {CurrencyDisplay::CODE, CurrencyDisplay::SYMBOL,
1211 CurrencyDisplay::NAME, CurrencyDisplay::NARROW_SYMBOL},
1212 CurrencyDisplay::SYMBOL);
1214 CurrencyDisplay currency_display = maybe_currency_display.
FromJust();
1216 CurrencySign currency_sign = CurrencySign::STANDARD;
1220 isolate, options,
"currencySign", service, {
"standard",
"accounting"},
1221 {CurrencySign::STANDARD, CurrencySign::ACCOUNTING},
1222 CurrencySign::STANDARD);
1224 currency_sign = maybe_currency_sign.
FromJust();
1228 std::unique_ptr<char[]> unit_cstr;
1230 empty_values, service, &unit_cstr);
1233 std::pair<icu::MeasureUnit, icu::MeasureUnit> unit_pair;
1237 std::string
unit = unit_cstr.get();
1241 IsWellFormedUnitIdentifier(isolate,
unit);
1242 if (maybe_wellformed_unit.
IsNothing()) {
1245 NewRangeError(MessageTemplate::kInvalidUnit,
1249 unit_pair = maybe_wellformed_unit.
FromJust();
1253 if (
style == Style::UNIT) {
1255 NewTypeError(MessageTemplate::kInvalidUnit,
1257 factory->empty_string()));
1264 isolate, options,
"unitDisplay", service, {
"short",
"narrow",
"long"},
1265 {UnitDisplay::SHORT, UnitDisplay::NARROW, UnitDisplay::LONG},
1266 UnitDisplay::SHORT);
1268 UnitDisplay unit_display = maybe_unit_display.
FromJust();
1271 icu::UnicodeString currency_ustr;
1272 if (
style == Style::CURRENCY) {
1275 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCurrencyCode));
1279 std::transform(currency.begin(), currency.end(), currency.begin(), toupper);
1280 currency_ustr = currency.c_str();
1283 if (!currency_ustr.isEmpty()) {
1289 settings.unit(icu::CurrencyUnit(currency_ustr.getBuffer(), status));
1290 DCHECK(U_SUCCESS(status));
1294 if (currency_display != CurrencyDisplay::SYMBOL) {
1295 settings = settings.unitWidth(ToUNumberUnitWidth(currency_display));
1297 DCHECK(U_SUCCESS(status));
1302 if (
style == Style::UNIT) {
1306 icu::MeasureUnit
none = icu::MeasureUnit();
1309 settings = settings.unit(unit_pair.first);
1312 settings = settings.perUnit(unit_pair.second);
1317 if (unit_display != UnitDisplay::SHORT) {
1318 settings = settings.unitWidth(ToUNumberUnitWidth(unit_display));
1324 if (
style == Style::PERCENT) {
1325 settings = settings.unit(icu::MeasureUnit::getPercent())
1326 .scale(icu::number::Scale::powerOfTen(2));
1329 Notation notation = Notation::STANDARD;
1335 isolate, options,
"notation", service,
1336 {
"standard",
"scientific",
"engineering",
"compact"},
1337 {Notation::STANDARD, Notation::SCIENTIFIC, Notation::ENGINEERING,
1339 Notation::STANDARD),
1344 int mnfd_default, mxfd_default;
1345 if (
style == Style::CURRENCY && notation == Notation::STANDARD) {
1347 int c_digits = CurrencyDigits(currency_ustr);
1350 mnfd_default = c_digits;
1351 mxfd_default = c_digits;
1357 if (
style == Style::PERCENT) {
1372 notation == Notation::COMPACT, service);
1378 mxfd_default = mnfd_default;
1390 isolate, options,
"compactDisplay", service, {
"short",
"long"},
1391 {CompactDisplay::SHORT, CompactDisplay::LONG}, CompactDisplay::SHORT);
1393 CompactDisplay compact_display = maybe_compact_display.
FromJust();
1397 if (notation != Notation::STANDARD) {
1398 settings = settings.notation(ToICUNotation(notation, compact_display));
1402 UseGrouping default_use_grouping = UseGrouping::AUTO;
1405 if (notation == Notation::COMPACT) {
1409 default_use_grouping = UseGrouping::MIN2;
1415 isolate, options,
"useGrouping", service, {
"min2",
"auto",
"always"},
1416 {UseGrouping::MIN2, UseGrouping::AUTO, UseGrouping::ALWAYS},
1417 UseGrouping::ALWAYS,
1419 default_use_grouping);
1421 UseGrouping use_grouping = maybe_use_grouping.
FromJust();
1423 if (use_grouping != UseGrouping::AUTO) {
1424 settings = settings.grouping(ToUNumberGroupingStrategy(use_grouping));
1431 isolate, options,
"signDisplay", service,
1432 {
"auto",
"never",
"always",
"exceptZero",
"negative"},
1433 {SignDisplay::AUTO, SignDisplay::NEVER, SignDisplay::ALWAYS,
1434 SignDisplay::EXCEPT_ZERO, SignDisplay::NEGATIVE},
1437 SignDisplay sign_display = maybe_sign_display.
FromJust();
1443 if (sign_display != SignDisplay::AUTO ||
1444 currency_sign != CurrencySign::STANDARD) {
1445 settings = settings.sign(ToUNumberSignDisplay(sign_display, currency_sign));
1462 icu::number::LocalizedNumberFormatter fmt = settings.locale(icu_locale);
1465 managed_number_formatter =
1468 std::make_shared<icu::number::LocalizedNumberFormatter>(fmt));
1472 isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
1474 number_format->set_locale(*locale_str);
1476 number_format->set_icu_number_formatter(*managed_number_formatter);
1477 number_format->set_bound_format(*factory->undefined_value());
1480 return number_format;
1485icu::number::FormattedNumber FormatDecimalString(
1487 const icu::number::LocalizedNumberFormatter& number_format,
1492 int32_t length =
static_cast<int32_t
>(
string->length());
1494 const char* char_buffer =
1496 return number_format.formatDecimal({char_buffer, length},
status);
1498 return number_format.formatDecimal({
string->ToCString().get(), length},
1509 return isolate->factory()->NumberToString(
value_);
1521 const icu::number::LocalizedNumberFormatter& number_format,
1525 UErrorCode status = U_ZERO_ERROR;
1526 if (IsBigInt(*numeric_obj)) {
1535 int32_t length =
static_cast<int32_t
>(big_int_string->length());
1537 const char* char_buffer =
1539 formatted = number_format.formatDecimal({char_buffer, length},
status);
1541 if (IsString(*numeric_obj)) {
1544 DirectHandle<String>
string =
1547 const String::FlatContent& flat =
string->GetFlatContent(no_gc);
1548 int32_t length =
static_cast<int32_t
>(
string->length());
1549 if (flat.IsOneByte()) {
1550 const char* char_buffer =
1551 reinterpret_cast<const char*
>(flat.ToOneByteVector().begin());
1552 formatted = number_format.formatDecimal({char_buffer, length},
status);
1559 formatted = number_format.formatDecimal(
1560 {
string->ToCString().get(), length},
status);
1563 double number =
IsNaN(*numeric_obj)
1564 ? std::numeric_limits<double>::quiet_NaN()
1565 : Object::NumberValue(*numeric_obj);
1566 formatted = number_format.formatDouble(number, status);
1569 if (U_FAILURE(status)) {
1573 NewTypeError(MessageTemplate::kIcuError),
1583 const icu::number::LocalizedNumberFormatter& number_format,
1585 if (IsString(*
x.value_)) {
1589 UErrorCode status = U_ZERO_ERROR;
1590 icu::number::FormattedNumber
result =
1591 FormatDecimalString(isolate, number_format,
string, status);
1592 if (U_FAILURE(status)) {
1594 NewTypeError(MessageTemplate::kIcuError),
1600 return IcuFormatNumber(isolate, number_format,
x.value_);
1605 const icu::number::LocalizedNumberRangeFormatter& number_range_format,
1607 icu::Formattable x_formatable;
1609 isolate, x_formatable,
x.ToFormattable(isolate),
1612 icu::Formattable y_formatable;
1614 isolate, y_formatable,
y.ToFormattable(isolate),
1617 UErrorCode status = U_ZERO_ERROR;
1618 icu::number::FormattedNumberRange
result =
1619 number_range_format.formatFormattableRange(x_formatable, y_formatable,
1621 if (U_FAILURE(status)) {
1623 NewTypeError(MessageTemplate::kIcuError),
1633template <
typename Char>
1634std::pair<int, int> FindLeadingAndTrailingWhiteSpaceOrLineTerminator(
1636 size_t leading_end = 0;
1639 while (leading_end < src.size() &&
1641 static_cast<uint16_t
>(src.at(leading_end)))) {
1644 size_t trailing_start = src.size();
1646 while (trailing_start > leading_end &&
1648 static_cast<uint16_t
>(src.at(trailing_start - 1)))) {
1651 return std::make_pair(leading_end, trailing_start);
1654Handle<String> TrimWhiteSpaceOrLineTerminator(Isolate* isolate,
1655 Handle<String>
string) {
1657 std::pair<int, uint32_t> whitespace_offsets;
1660 String::FlatContent flat =
string->GetFlatContent(no_gc);
1661 if (flat.IsOneByte()) {
1662 whitespace_offsets = FindLeadingAndTrailingWhiteSpaceOrLineTerminator(
1663 flat.ToOneByteVector());
1665 whitespace_offsets =
1666 FindLeadingAndTrailingWhiteSpaceOrLineTerminator(flat.ToUC16Vector());
1669 if (whitespace_offsets.first == 0 &&
1670 string->length() == whitespace_offsets.second) {
1673 return isolate->factory()->NewSubString(
string, whitespace_offsets.first,
1674 whitespace_offsets.second);
1682 Factory* factory = isolate->factory();
1685 if (IsJSReceiver(*value)) {
1687 isolate, prim_value,
1697 if (IsBigInt(*prim_value)) {
1698 result.value_ = prim_value;
1702 if (IsOddball(*prim_value)) {
1706 result.value_ = prim_value;
1710 if (!IsString(*prim_value)) {
1720 string = TrimWhiteSpaceOrLineTerminator(isolate,
string);
1721 if (string->length() == 0) {
1727 if (2 < string->length() && string->Get(0) ==
'0') {
1728 uint16_t ch =
string->Get(1);
1729 if (ch ==
'b' || ch ==
'B' || ch ==
'o' || ch ==
'O' || ch ==
'x' ||
1735 result.value_ = isolate->factory()->NewNumber(
result.approx_);
1742 isolate->clear_exception();
1743 result.value_ = factory->nan_value();
1753 if (std::isnan(
result.approx_)) {
1754 result.value_ = factory->nan_value();
1758 if (!std::isfinite(
result.approx_)) {
1759 if (
result.approx_ < 0) {
1760 result.value_ = factory->minus_infinity_value();
1762 result.value_ = factory->infinity_value();
1781 UErrorCode status = U_ZERO_ERROR;
1785 int32_t length =
static_cast<int32_t
>(
string->length());
1793 icu::Formattable
result({
string->ToCString().get(), length},
status);
1798 NewTypeError(MessageTemplate::kIcuError),
1806 if (a.begin_pos < b.
begin_pos)
return true;
1807 if (a.begin_pos > b.
begin_pos)
return false;
1810 if (a.end_pos < b.
end_pos)
return false;
1811 if (a.end_pos > b.
end_pos)
return true;
1826 std::vector<NumberFormatSpan>* regions) {
1858 std::sort(regions->begin(), regions->end(), cmp_NumberFormatSpan);
1859 std::vector<size_t> overlapping_region_index_stack;
1862 overlapping_region_index_stack.push_back(0);
1864 size_t region_iterator = 1;
1865 int32_t entire_size = top_region.
end_pos;
1867 std::vector<NumberFormatSpan> out_parts;
1872 int32_t climber = 0;
1873 while (climber < entire_size) {
1874 int32_t next_region_begin_pos;
1875 if (region_iterator < regions->
size()) {
1876 next_region_begin_pos = regions->at(region_iterator).begin_pos;
1879 next_region_begin_pos = entire_size;
1882 if (climber < next_region_begin_pos) {
1883 while (top_region.
end_pos < next_region_begin_pos) {
1884 if (climber < top_region.
end_pos) {
1892 overlapping_region_index_stack.pop_back();
1893 top_region = regions->at(overlapping_region_index_stack.back());
1895 if (climber < next_region_begin_pos) {
1898 next_region_begin_pos));
1899 climber = next_region_begin_pos;
1902 if (region_iterator < regions->
size()) {
1903 overlapping_region_index_stack.push_back(region_iterator++);
1904 top_region = regions->at(overlapping_region_index_stack.back());
1913 DirectHandle<JSArray>
result,
int start_index,
1914 bool style_is_unit,
bool is_nan,
bool output_source,
1915 bool output_unit, DirectHandle<String>
unit) {
1916 UErrorCode status = U_ZERO_ERROR;
1917 icu::UnicodeString formatted_text =
formatted.toString(status);
1918 if (U_FAILURE(status)) {
1920 isolate, NewTypeError(MessageTemplate::kIcuError),
Nothing<int>());
1922 int32_t length = formatted_text.length();
1923 int index = start_index;
1924 if (length == 0)
return Just(index);
1926 std::vector<NumberFormatSpan> regions;
1931 regions.push_back(NumberFormatSpan(-1, 0, formatted_text.length()));
1932 Intl::FormatRangeSourceTracker tracker;
1934 icu::ConstrainedFieldPosition cfpos;
1935 while (
formatted.nextPosition(cfpos, status)) {
1936 int32_t category = cfpos.getCategory();
1937 int32_t field = cfpos.getField();
1938 int32_t
start = cfpos.getStart();
1939 int32_t limit = cfpos.getLimit();
1940 if (category == UFIELD_CATEGORY_NUMBER_RANGE_SPAN) {
1942 tracker.Add(field,
start, limit);
1944 regions.push_back(NumberFormatSpan(field,
start, limit));
1951 for (
auto it = parts.begin(); it < parts.end(); it++) {
1952 NumberFormatSpan part = *it;
1953 DirectHandle<String> field_type_string =
1954 isolate->factory()->literal_string();
1955 if (part.field_id != -1) {
1956 if (style_is_unit &&
static_cast<UNumberFormatFields
>(part.field_id) ==
1957 UNUM_PERCENT_FIELD) {
1959 field_type_string = isolate->factory()->unit_string();
1968 Intl::ToString(isolate, formatted_text, part.begin_pos, part.end_pos),
1971 if (output_source) {
1973 isolate,
result, index, field_type_string, substring,
1974 isolate->factory()->source_string(),
1976 tracker.GetSource(part.begin_pos, part.end_pos)));
1980 isolate->factory()->unit_string(),
unit);
1997 return ConstructParts(isolate,
formatted,
result, start_index,
true,
false,
2004template <typename T, MaybeDirectHandle<T> (*
F)(
2005 Isolate*,
const icu::FormattedValue&,
2006 const icu::number::LocalizedNumberFormatter&,
bool)>
2010 Factory* factory = isolate->factory();
2026 NewRangeError(MessageTemplate::kInvalid,
2033 NewRangeError(MessageTemplate::kInvalid,
2035 MaybeDirectHandle<T>());
2038 Maybe<icu::number::LocalizedNumberRangeFormatter> maybe_range_formatter =
2040 isolate, number_format->locale(),
2041 *number_format->icu_number_formatter()->raw());
2042 MAYBE_RETURN(maybe_range_formatter, MaybeDirectHandle<T>());
2044 icu::number::LocalizedNumberRangeFormatter nrfmt =
2045 maybe_range_formatter.FromJust();
2047 Maybe<icu::number::FormattedNumberRange> maybe_formatted =
2050 icu::number::FormattedNumberRange
formatted =
2051 std::move(maybe_formatted).FromJust();
2053 return F(isolate,
formatted, *(number_format->icu_number_formatter()->raw()),
2057MaybeDirectHandle<String> FormatToString(
2058 Isolate* isolate,
const icu::FormattedValue&
formatted,
2059 const icu::number::LocalizedNumberFormatter&,
bool) {
2060 UErrorCode status = U_ZERO_ERROR;
2062 if (U_FAILURE(status)) {
2068MaybeDirectHandle<JSArray> FormatToJSArray(
2069 Isolate* isolate,
const icu::FormattedValue&
formatted,
2070 const icu::number::LocalizedNumberFormatter& nfmt,
bool is_nan,
2071 bool output_source) {
2072 UErrorCode status = U_ZERO_ERROR;
2073 bool is_unit = Style::UNIT == StyleFromSkeleton(nfmt.toSkeleton(status));
2074 CHECK(U_SUCCESS(status));
2076 Factory* factory = isolate->factory();
2077 DirectHandle<JSArray>
result = factory->NewJSArray(0);
2079 int format_to_parts;
2081 isolate, format_to_parts,
2083 output_source,
false, DirectHandle<String>()),
2084 DirectHandle<JSArray>());
2085 USE(format_to_parts);
2090MaybeDirectHandle<JSArray> FormatRangeToJSArray(
2091 Isolate* isolate,
const icu::FormattedValue&
formatted,
2092 const icu::number::LocalizedNumberFormatter& nfmt,
bool is_nan) {
2093 return FormatToJSArray(isolate,
formatted, nfmt, is_nan,
true);
2098Maybe<icu::number::LocalizedNumberRangeFormatter>
2101 const icu::number::LocalizedNumberFormatter& number_formatter) {
2102 UErrorCode status = U_ZERO_ERROR;
2104 icu::number::LocalizedNumberRangeFormatter range_formatter =
2105 icu::number::UnlocalizedNumberRangeFormatter()
2106 .numberFormatterBoth(icu::number::NumberFormatter::forSkeleton(
2107 number_formatter.toSkeleton(status), perror, status))
2109 icu::Locale::forLanguageTag(locale->ToCString().get(), status));
2110 if (U_FAILURE(status)) {
2112 isolate, NewTypeError(MessageTemplate::kIcuError),
2115 return Just(range_formatter);
2120 const icu::number::LocalizedNumberFormatter& number_format,
2123 IcuFormatNumber(isolate, number_format, numeric_obj);
2125 icu::number::FormattedNumber
formatted = std::move(maybe_format).FromJust();
2127 return FormatToString(isolate,
formatted, number_format,
IsNaN(*numeric_obj));
2133 icu::number::LocalizedNumberFormatter* fmt =
2134 number_format->icu_number_formatter()->raw();
2147 icu::number::FormattedNumber
formatted =
2148 std::move(maybe_formatted).FromJust();
2150 return FormatToString(isolate,
formatted, *fmt,
x.IsNaN());
2156 icu::number::LocalizedNumberFormatter* fmt =
2157 number_format->icu_number_formatter()->raw();
2167 icu::number::FormattedNumber
formatted =
2168 std::move(maybe_formatted).FromJust();
2170 return FormatToJSArray(isolate,
formatted, *fmt, value.IsNaN(),
false);
2178 return PartitionNumberRangePattern<String, FormatToString>(
2179 isolate, number_format, x_obj, y_obj,
2180 "Intl.NumberFormat.prototype.formatRange");
2186 return PartitionNumberRangePattern<JSArray, FormatRangeToJSArray>(
2187 isolate, number_format, x_obj, y_obj,
2188 "Intl.NumberFormat.prototype.formatRangeToParts");
2193struct CheckNumberElements {
2194 static const char*
key() {
return "NumberElements"; }
2195 static const char* path() {
return nullptr; }
2203 return available_locales.Pointer()->Get();
V8_INLINE T FromJust() const &
V8_INLINE bool IsNothing() const
static MaybeHandle< String > ToString(Isolate *isolate, DirectHandle< BigInt > bigint, int radix=10, ShouldThrow should_throw=kThrowOnError)
Handle< Number > NewNumberFromInt(int32_t value)
Handle< String > NewStringFromAsciiChecked(const char *str, AllocationType allocation=AllocationType::kYoung)
Handle< JSObject > NewJSObject(DirectHandle< JSFunction > constructor, AllocationType allocation=AllocationType::kYoung, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
Handle< String > NewStringFromStaticChars(const char(&str)[N], AllocationType allocation=AllocationType::kYoung)
Maybe< icu::Formattable > ToFormattable(Isolate *isolate) const
static Maybe< icu::number::FormattedNumberRange > FormatRange(Isolate *isolate, const icu::number::LocalizedNumberRangeFormatter &number_range_format, const IntlMathematicalValue &x, const IntlMathematicalValue &y)
static V8_EXPORT_PRIVATE Maybe< IntlMathematicalValue > From(Isolate *isolate, Handle< Object > value)
MaybeHandle< String > ToString(Isolate *isolate) const
V8_EXPORT_PRIVATE bool IsNaN() const
static Maybe< icu::number::FormattedNumber > FormatNumeric(Isolate *isolate, const icu::number::LocalizedNumberFormatter &number_format, const IntlMathematicalValue &x)
static void AddElement(Isolate *isolate, DirectHandle< JSArray > array, int index, DirectHandle< String > field_type_string, DirectHandle< String > value)
static std::string GetNumberingSystem(const icu::Locale &icu_locale)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > LegacyUnwrapReceiver(Isolate *isolate, DirectHandle< JSReceiver > receiver, DirectHandle< JSFunction > constructor, bool has_initialized_slot)
static V8_WARN_UNUSED_RESULT MaybeHandle< String > ToString(Isolate *isolate, const icu::UnicodeString &string)
static Maybe< int > AddNumberElements(Isolate *isolate, const icu::FormattedValue &formatted, DirectHandle< JSArray > result, int start_index, DirectHandle< String > unit)
static Maybe< std::vector< std::string > > CanonicalizeLocaleList(Isolate *isolate, DirectHandle< Object > locales, bool only_return_one_result=false)
static Maybe< ResolvedLocale > ResolveLocale(Isolate *isolate, const std::set< std::string > &available_locales, const std::vector< std::string > &requested_locales, MatcherOption options, const std::set< std::string > &relevant_extension_keys)
static std::set< std::string > SanctionedSimpleUnits()
static V8_WARN_UNUSED_RESULT Maybe< MatcherOption > GetLocaleMatcher(Isolate *isolate, DirectHandle< JSReceiver > options, const char *method_name)
static Maybe< std::string > ToLanguageTag(const icu::Locale &locale)
static V8_WARN_UNUSED_RESULT Maybe< NumberFormatDigitOptions > SetNumberFormatDigitOptions(Isolate *isolate, DirectHandle< JSReceiver > options, int mnfd_default, int mxfd_default, bool notation_is_compact, const char *service)
static bool IsValidNumberingSystem(const std::string &value)
static DirectHandle< String > SourceString(Isolate *isolate, FormatRangeSource source)
static DirectHandle< String > NumberFieldToType(Isolate *isolate, const NumberFormatSpan &part, const icu::UnicodeString &text, bool is_nan)
static void ValidateElements(Tagged< JSObject > object)
static V8_WARN_UNUSED_RESULT HandleType< Object >::MaybeType ToPrimitive(Isolate *isolate, HandleType< JSReceiver > receiver, ToPrimitiveHint hint=ToPrimitiveHint::kDefault)
static V8_WARN_UNUSED_RESULT Maybe< bool > CreateDataProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > key, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
static DirectHandle< Managed< CppType > > From(Isolate *isolate, size_t estimated_size, std::shared_ptr< CppType > shared_ptr, AllocationType allocation_type=AllocationType::kYoung)
V8_INLINE Handle< T > ToHandleChecked() const
static V8_WARN_UNUSED_RESULT HandleType< Number >::MaybeType ToNumber(Isolate *isolate, HandleType< T > input)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT Handle< Number > ToNumber(Isolate *isolate, DirectHandle< Oddball > input)
static constexpr Tagged< Smi > zero()
base::Vector< const uint8_t > ToOneByteVector() const
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
#define THROW_NEW_ERROR_RETURN_VALUE(isolate, call, value)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
#define MAYBE_RETURN(call, value)
#define MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
DirectHandle< JSReceiver > options
RoundingMode rounding_mode
ZoneVector< RpoNumber > & result
#define LAZY_INSTANCE_INITIALIZER
std::priority_queue< BigUnit > units[CompilationTier::kNumTiers]
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
constexpr double kMaxSafeInteger
bool IsNaN(Tagged< Object > obj)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
bool IsNumber(Tagged< Object > obj)
bool IsWhiteSpaceOrLineTerminator(base::uc32 c)
V8_EXPORT_PRIVATE std::vector< NumberFormatSpan > FlattenRegionsToParts(std::vector< NumberFormatSpan > *regions)
constexpr bool IsDecimalDigit(base::uc32 c)
@ ALLOW_NON_DECIMAL_PREFIX
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long enable use of partial constant none
MaybeDirectHandle< JSReceiver > CoerceOptionsToObject(Isolate *isolate, DirectHandle< Object > options, const char *method_name)
constexpr int AsciiAlphaToLower(base::uc32 c)
static V8_WARN_UNUSED_RESULT Maybe< T > GetStringOrBooleanOption(Isolate *isolate, DirectHandle< JSReceiver > options, const char *property, const char *method, const std::vector< const char * > &str_values, const std::vector< T > &enum_values, T true_value, T false_value, T fallback_value)
Maybe< bool > GetStringOption(Isolate *isolate, DirectHandle< JSReceiver > options, const char *property, const std::vector< const char * > &values, const char *method_name, std::unique_ptr< char[]> *result)
double StringToDouble(const char *str, ConversionFlag flags, double empty_string_val)
template const char * string
MaybeHandle< BigInt > StringToBigInt(Isolate *isolate, DirectHandle< String > string)
!IsContextMap !IsContextMap native_context
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Maybe< T > Just(const T &t)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define CHECK_NOT_NULL(val)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
typename LazyStaticInstance< T, CreateTrait, InitOnceTrait, DestroyTrait >::type type