Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (260410 => 260411)
--- trunk/Source/_javascript_Core/ChangeLog 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-04-21 04:04:10 UTC (rev 260411)
@@ -1,3 +1,54 @@
+2020-04-20 Ross Kirsling <ross.kirsl...@sony.com>
+
+ Intl classes shouldn't need an m_initialized* field
+ https://bugs.webkit.org/show_bug.cgi?id=210764
+
+ Reviewed by Darin Adler.
+
+ Existing Intl classes each have a field like m_initializedNumberFormat, but this is unnecessary on two levels:
+ 1. The thing that gets initialized is a unique pointer to an ICU struct, so we can check it directly.
+ 2. Everywhere we're checking this is redundant since we've already done the same check on the prototype side,
+ therefore we can just ASSERT before using said ICU struct.
+
+ While we're at it, clean up other stuff like:
+ - Move stuff that doesn't need to be part of the class to the CPP file (e.g. UFieldPositionIteratorDeleter).
+ - Merge createCollator into initializeCollator (seems like this is probably the oldest code in this space).
+
+ * runtime/IntlCollator.cpp:
+ (JSC::IntlCollator::initializeCollator):
+ (JSC::IntlCollator::compareStrings):
+ (JSC::IntlCollator::resolvedOptions):
+ (JSC::IntlCollator::createCollator): Deleted.
+ * runtime/IntlCollator.h:
+ * runtime/IntlDateTimeFormat.cpp:
+ (JSC::UFieldPositionIteratorDeleter::operator() const):
+ (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+ (JSC::IntlDateTimeFormat::resolvedOptions):
+ (JSC::IntlDateTimeFormat::format):
+ (JSC::partTypeString):
+ (JSC::IntlDateTimeFormat::formatToParts):
+ (JSC::IntlDateTimeFormat::UFieldPositionIteratorDeleter::operator() const): Deleted.
+ (JSC::IntlDateTimeFormat::partTypeString): Deleted.
+ * runtime/IntlDateTimeFormat.h:
+ * runtime/IntlNumberFormat.cpp:
+ (JSC::UFieldPositionIteratorDeleter::operator() const):
+ (JSC::IntlNumberFormatField::IntlNumberFormatField):
+ (JSC::IntlNumberFormat::initializeNumberFormat):
+ (JSC::IntlNumberFormat::format):
+ (JSC::IntlNumberFormat::resolvedOptions):
+ (JSC::partTypeString):
+ (JSC::IntlNumberFormat::formatToParts):
+ (JSC::IntlNumberFormat::UFieldPositionIteratorDeleter::operator() const): Deleted.
+ (JSC::IntlNumberFormat::partTypeString): Deleted.
+ * runtime/IntlNumberFormat.h:
+ * runtime/IntlPluralRules.cpp:
+ (JSC::localeData):
+ (JSC::IntlPluralRules::initializePluralRules):
+ (JSC::IntlPluralRules::resolvedOptions):
+ (JSC::IntlPluralRules::select):
+ (JSC::IntlPRInternal::localeData): Deleted.
+ * runtime/IntlPluralRules.h:
+
2020-04-20 Keith Miller <keith_mil...@apple.com>
FTL doesn't observe the use kind of CheckIsConstant's child1
Modified: trunk/Source/_javascript_Core/runtime/IntlCollator.cpp (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlCollator.cpp 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlCollator.cpp 2020-04-21 04:04:10 UTC (rev 260411)
@@ -165,14 +165,12 @@
return keyLocaleData;
}
+// https://tc39.github.io/ecma402/#sec-initializecollator
void IntlCollator::initializeCollator(JSGlobalObject* globalObject, JSValue locales, JSValue optionsValue)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 10.1.1 InitializeCollator (collator, locales, options) (ECMA-402)
- // https://tc39.github.io/ecma402/#sec-initializecollator
-
auto requestedLocales = canonicalizeLocaleList(globalObject, locales);
RETURN_IF_EXCEPTION(scope, void());
@@ -229,10 +227,10 @@
m_collation = collation.isNull() ? "default"_s : collation;
m_numeric = result.get("kn"_s) == "true";
- const String& caseFirst = result.get("kf"_s);
- if (caseFirst == "lower")
+ const String& caseFirstString = result.get("kf"_s);
+ if (caseFirstString == "lower")
m_caseFirst = CaseFirst::Lower;
- else if (caseFirst == "upper")
+ else if (caseFirstString == "upper")
m_caseFirst = CaseFirst::Upper;
else
m_caseFirst = CaseFirst::False;
@@ -250,29 +248,17 @@
bool usesFallback;
bool ignorePunctuation = intlBooleanOption(globalObject, options, vm.propertyNames->ignorePunctuation, usesFallback);
+ RETURN_IF_EXCEPTION(scope, void());
if (usesFallback)
ignorePunctuation = false;
- RETURN_IF_EXCEPTION(scope, void());
m_ignorePunctuation = ignorePunctuation;
- m_initializedCollator = true;
-}
-
-void IntlCollator::createCollator(JSGlobalObject* globalObject)
-{
- VM& vm = globalObject->vm();
- auto scope = DECLARE_CATCH_SCOPE(vm);
- ASSERT(!m_collator);
-
- if (!m_initializedCollator) {
- initializeCollator(globalObject, jsUndefined(), jsUndefined());
- scope.assertNoException();
- }
-
UErrorCode status = U_ZERO_ERROR;
- auto collator = std::unique_ptr<UCollator, UCollatorDeleter>(ucol_open(m_locale.utf8().data(), &status));
- if (U_FAILURE(status))
+ m_collator = std::unique_ptr<UCollator, UCollatorDeleter>(ucol_open(m_locale.utf8().data(), &status));
+ if (U_FAILURE(status)) {
+ throwTypeError(globalObject, scope, "failed to initialize Collator"_s);
return;
+ }
UColAttributeValue strength = UCOL_PRIMARY;
UColAttributeValue caseLevel = UCOL_OFF;
@@ -301,36 +287,29 @@
break;
}
- ucol_setAttribute(collator.get(), UCOL_STRENGTH, strength, &status);
- ucol_setAttribute(collator.get(), UCOL_CASE_LEVEL, caseLevel, &status);
- ucol_setAttribute(collator.get(), UCOL_CASE_FIRST, caseFirst, &status);
- ucol_setAttribute(collator.get(), UCOL_NUMERIC_COLLATION, m_numeric ? UCOL_ON : UCOL_OFF, &status);
+ ucol_setAttribute(m_collator.get(), UCOL_STRENGTH, strength, &status);
+ ucol_setAttribute(m_collator.get(), UCOL_CASE_LEVEL, caseLevel, &status);
+ ucol_setAttribute(m_collator.get(), UCOL_CASE_FIRST, caseFirst, &status);
+ ucol_setAttribute(m_collator.get(), UCOL_NUMERIC_COLLATION, m_numeric ? UCOL_ON : UCOL_OFF, &status);
// FIXME: Setting UCOL_ALTERNATE_HANDLING to UCOL_SHIFTED causes punctuation and whitespace to be
// ignored. There is currently no way to ignore only punctuation.
- ucol_setAttribute(collator.get(), UCOL_ALTERNATE_HANDLING, m_ignorePunctuation ? UCOL_SHIFTED : UCOL_DEFAULT, &status);
+ ucol_setAttribute(m_collator.get(), UCOL_ALTERNATE_HANDLING, m_ignorePunctuation ? UCOL_SHIFTED : UCOL_DEFAULT, &status);
// "The method is required to return 0 when comparing Strings that are considered canonically
// equivalent by the Unicode standard."
- ucol_setAttribute(collator.get(), UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
- if (U_FAILURE(status))
- return;
-
- m_collator = WTFMove(collator);
+ ucol_setAttribute(m_collator.get(), UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
+ ASSERT(U_SUCCESS(status));
}
+// https://tc39.es/ecma402/#sec-collator-comparestrings
JSValue IntlCollator::compareStrings(JSGlobalObject* globalObject, StringView x, StringView y)
{
+ ASSERT(m_collator);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 10.3.4 CompareStrings abstract operation (ECMA-402 2.0)
- if (!m_collator) {
- createCollator(globalObject);
- if (!m_collator)
- return throwException(globalObject, scope, createError(globalObject, "Failed to compare strings."_s));
- }
-
UErrorCode status = U_ZERO_ERROR;
UCollationResult result = UCOL_EQUAL;
if (x.is8Bit() && y.is8Bit() && x.isAllASCII() && y.isAllASCII())
@@ -397,25 +376,10 @@
return ASCIILiteral::null();
}
+// https://tc39.es/ecma402/#sec-intl.collator.prototype.resolvedoptions
JSObject* IntlCollator::resolvedOptions(JSGlobalObject* globalObject)
{
VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- // 10.3.5 Intl.Collator.prototype.resolvedOptions() (ECMA-402 2.0)
- // The function returns a new object whose properties and attributes are set as if
- // constructed by an object literal assigning to each of the following properties the
- // value of the corresponding internal slot of this Collator object (see 10.4): locale,
- // usage, sensitivity, ignorePunctuation, collation, as well as those properties shown
- // in Table 1 whose keys are included in the %Collator%[[relevantExtensionKeys]]
- // internal slot of the standard built-in object that is the initial value of
- // Intl.Collator.
-
- if (!m_initializedCollator) {
- initializeCollator(globalObject, jsUndefined(), jsUndefined());
- scope.assertNoException();
- }
-
JSObject* options = constructEmptyObject(globalObject);
options->putDirect(vm, vm.propertyNames->locale, jsString(vm, m_locale));
options->putDirect(vm, vm.propertyNames->usage, jsNontrivialString(vm, usageString(m_usage)));
Modified: trunk/Source/_javascript_Core/runtime/IntlCollator.h (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlCollator.h 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlCollator.h 2020-04-21 04:04:10 UTC (rev 260411)
@@ -76,21 +76,20 @@
void operator()(UCollator*) const;
};
- void createCollator(JSGlobalObject*);
static ASCIILiteral usageString(Usage);
static ASCIILiteral sensitivityString(Sensitivity);
static ASCIILiteral caseFirstString(CaseFirst);
+ WriteBarrier<JSBoundFunction> m_boundCompare;
+ std::unique_ptr<UCollator, UCollatorDeleter> m_collator;
+
String m_locale;
String m_collation;
- WriteBarrier<JSBoundFunction> m_boundCompare;
- std::unique_ptr<UCollator, UCollatorDeleter> m_collator;
Usage m_usage;
Sensitivity m_sensitivity;
CaseFirst m_caseFirst;
bool m_numeric;
bool m_ignorePunctuation;
- bool m_initializedCollator { false };
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp 2020-04-21 04:04:10 UTC (rev 260411)
@@ -54,6 +54,14 @@
static const size_t indexOfExtensionKeyNu = 1;
static const size_t indexOfExtensionKeyHc = 2;
+struct UFieldPositionIteratorDeleter {
+ void operator()(UFieldPositionIterator* iterator) const
+ {
+ if (iterator)
+ ufieldpositer_close(iterator);
+ }
+};
+
void IntlDateTimeFormat::UDateFormatDeleter::operator()(UDateFormat* dateFormat) const
{
if (dateFormat)
@@ -60,12 +68,6 @@
udat_close(dateFormat);
}
-void IntlDateTimeFormat::UFieldPositionIteratorDeleter::operator()(UFieldPositionIterator* iterator) const
-{
- if (iterator)
- ufieldpositer_close(iterator);
-}
-
IntlDateTimeFormat* IntlDateTimeFormat::create(VM& vm, Structure* structure)
{
IntlDateTimeFormat* format = new (NotNull, allocateCell<IntlDateTimeFormat>(vm.heap)) IntlDateTimeFormat(vm, structure);
@@ -437,14 +439,12 @@
}
}
+// https://tc39.github.io/ecma402/#sec-initializedatetimeformat
void IntlDateTimeFormat::initializeDateTimeFormat(JSGlobalObject* globalObject, JSValue locales, JSValue originalOptions)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 12.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options) (ECMA-402)
- // https://tc39.github.io/ecma402/#sec-initializedatetimeformat
-
Vector<String> requestedLocales = canonicalizeLocaleList(globalObject, locales);
RETURN_IF_EXCEPTION(scope, void());
@@ -701,8 +701,6 @@
// Failure here means unsupported calendar, and can safely be ignored.
UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(m_dateFormat.get()));
ucal_setGregorianChange(cal, minECMAScriptTime, &status);
-
- m_initializedDateTimeFormat = true;
}
ASCIILiteral IntlDateTimeFormat::weekdayString(Weekday weekday)
@@ -850,19 +848,11 @@
return ASCIILiteral::null();
}
+// https://tc39.es/ecma402/#sec-intl.datetimeformat.prototype.resolvedoptions
JSObject* IntlDateTimeFormat::resolvedOptions(JSGlobalObject* globalObject)
{
VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
- // 12.3.5 Intl.DateTimeFormat.prototype.resolvedOptions() (ECMA-402 2.0)
- // The function returns a new object whose properties and attributes are set as if constructed by an object literal assigning to each of the following properties the value of the corresponding internal slot of this DateTimeFormat object (see 12.4): locale, calendar, numberingSystem, timeZone, hour12, weekday, era, year, month, day, hour, minute, second, and timeZoneName. Properties whose corresponding internal slots are not present are not assigned.
- // Note: In this version of the ECMAScript 2015 Internationalization API, the timeZone property will be the name of the default time zone if no timeZone property was provided in the options object provided to the Intl.DateTimeFormat constructor. The previous version left the timeZone property undefined in this case.
- if (!m_initializedDateTimeFormat) {
- initializeDateTimeFormat(globalObject, jsUndefined(), jsUndefined());
- scope.assertNoException();
- }
-
JSObject* options = constructEmptyObject(globalObject);
options->putDirect(vm, vm.propertyNames->locale, jsNontrivialString(vm, m_locale));
options->putDirect(vm, vm.propertyNames->calendar, jsNontrivialString(vm, m_calendar));
@@ -904,22 +894,17 @@
return options;
}
+// https://tc39.es/ecma402/#sec-formatdatetime
JSValue IntlDateTimeFormat::format(JSGlobalObject* globalObject, double value)
{
+ ASSERT(m_dateFormat);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 12.3.4 FormatDateTime abstract operation (ECMA-402 2.0)
- if (!m_initializedDateTimeFormat) {
- initializeDateTimeFormat(globalObject, jsUndefined(), jsUndefined());
- scope.assertNoException();
- }
-
- // 1. If x is not a finite Number, then throw a RangeError exception.
if (!std::isfinite(value))
return throwRangeError(globalObject, scope, "date value is not finite in DateTimeFormat format()"_s);
- // Delegate remaining steps to ICU.
UErrorCode status = U_ZERO_ERROR;
Vector<UChar, 32> result(32);
auto resultLength = udat_format(m_dateFormat.get(), value, result.data(), result.size(), nullptr, &status);
@@ -934,7 +919,7 @@
return jsString(vm, String(result.data(), resultLength));
}
-ASCIILiteral IntlDateTimeFormat::partTypeString(UDateFormatField field)
+static ASCIILiteral partTypeString(UDateFormatField field)
{
switch (field) {
case UDAT_ERA_FIELD:
@@ -996,15 +981,14 @@
return "unknown"_s;
}
-
+// https://tc39.es/ecma402/#sec-formatdatetimetoparts
JSValue IntlDateTimeFormat::formatToParts(JSGlobalObject* globalObject, double value)
{
+ ASSERT(m_dateFormat);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 12.1.8 FormatDateTimeToParts (ECMA-402 4.0)
- // https://tc39.github.io/ecma402/#sec-formatdatetimetoparts
-
if (!std::isfinite(value))
return throwRangeError(globalObject, scope, "date value is not finite in DateTimeFormat formatToParts()"_s);
Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h 2020-04-21 04:04:10 UTC (rev 260411)
@@ -110,13 +110,6 @@
Minute m_minute { Minute::None };
Second m_second { Second::None };
TimeZoneName m_timeZoneName { TimeZoneName::None };
- bool m_initializedDateTimeFormat { false };
-
- struct UFieldPositionIteratorDeleter {
- void operator()(UFieldPositionIterator*) const;
- };
-
- static ASCIILiteral partTypeString(UDateFormatField);
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.cpp 2020-04-21 04:04:10 UTC (rev 260411)
@@ -44,6 +44,19 @@
static const char* const relevantNumberExtensionKeys[1] = { "nu" };
+struct UFieldPositionIteratorDeleter {
+ void operator()(UFieldPositionIterator* iterator) const
+ {
+ if (iterator)
+ ufieldpositer_close(iterator);
+ }
+};
+
+struct IntlNumberFormatField {
+ int32_t type;
+ size_t size;
+};
+
void IntlNumberFormat::UNumberFormatDeleter::operator()(UNumberFormat* numberFormat) const
{
if (numberFormat)
@@ -150,14 +163,12 @@
return 2;
}
+// https://tc39.github.io/ecma402/#sec-initializenumberformat
void IntlNumberFormat::initializeNumberFormat(JSGlobalObject* globalObject, JSValue locales, JSValue optionsValue)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 11.1.2 InitializeNumberFormat (numberFormat, locales, options) (ECMA-402)
- // https://tc39.github.io/ecma402/#sec-initializenumberformat
-
auto requestedLocales = canonicalizeLocaleList(globalObject, locales);
RETURN_IF_EXCEPTION(scope, void());
@@ -280,9 +291,9 @@
bool usesFallback;
bool useGrouping = intlBooleanOption(globalObject, options, Identifier::fromString(vm, "useGrouping"), usesFallback);
+ RETURN_IF_EXCEPTION(scope, void());
if (usesFallback)
useGrouping = true;
- RETURN_IF_EXCEPTION(scope, void());
m_useGrouping = useGrouping;
UNumberFormatStyle style = UNUM_DEFAULT;
@@ -337,19 +348,16 @@
}
unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, m_useGrouping);
unum_setAttribute(m_numberFormat.get(), UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP);
-
- m_initializedNumberFormat = true;
}
// https://tc39.es/ecma402/#sec-formatnumber
JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, double value)
{
+ ASSERT(m_numberFormat);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (!m_initializedNumberFormat)
- return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.format called on value that's not an object initialized as a NumberFormat"_s);
-
UErrorCode status = U_ZERO_ERROR;
Vector<UChar, 32> buffer(32);
auto length = unum_formatDouble(m_numberFormat.get(), value, buffer.data(), buffer.size(), nullptr, &status);
@@ -364,14 +372,14 @@
return jsString(vm, String(buffer.data(), length));
}
+// https://tc39.es/ecma402/#sec-formatnumber
JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, JSBigInt* value)
{
+ ASSERT(m_numberFormat);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (!m_initializedNumberFormat)
- return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.format called on value that's not an object initialized as a NumberFormat"_s);
-
auto string = value->toString(globalObject, 10);
RETURN_IF_EXCEPTION(scope, { });
@@ -420,25 +428,10 @@
return ASCIILiteral::null();
}
+// https://tc39.es/ecma402/#sec-intl.numberformat.prototype.resolvedoptions
JSObject* IntlNumberFormat::resolvedOptions(JSGlobalObject* globalObject)
{
VM& vm = globalObject->vm();
- auto scope = DECLARE_THROW_SCOPE(vm);
-
- // 11.3.5 Intl.NumberFormat.prototype.resolvedOptions() (ECMA-402 2.0)
- // The function returns a new object whose properties and attributes are set as if
- // constructed by an object literal assigning to each of the following properties the
- // value of the corresponding internal slot of this NumberFormat object (see 11.4):
- // locale, numberingSystem, style, currency, currencyDisplay, minimumIntegerDigits,
- // minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits,
- // maximumSignificantDigits, and useGrouping. Properties whose corresponding internal
- // slots are not present are not assigned.
-
- if (!m_initializedNumberFormat) {
- initializeNumberFormat(globalObject, jsUndefined(), jsUndefined());
- scope.assertNoException();
- }
-
JSObject* options = constructEmptyObject(globalObject);
options->putDirect(vm, vm.propertyNames->locale, jsString(vm, m_locale));
options->putDirect(vm, vm.propertyNames->numberingSystem, jsString(vm, m_numberingSystem));
@@ -464,14 +457,8 @@
m_boundFormat.set(vm, this, format);
}
-void IntlNumberFormat::UFieldPositionIteratorDeleter::operator()(UFieldPositionIterator* iterator) const
+static ASCIILiteral partTypeString(UNumberFormatFields field, double value)
{
- if (iterator)
- ufieldpositer_close(iterator);
-}
-
-ASCIILiteral IntlNumberFormat::partTypeString(UNumberFormatFields field, double value)
-{
switch (field) {
case UNUM_INTEGER_FIELD:
if (std::isnan(value))
@@ -512,17 +499,17 @@
auto stringLength = formatted.length();
int32_t literalFieldType = -1;
- auto literalField = IntlNumberFormatField(literalFieldType, stringLength);
+ IntlNumberFormatField literalField { literalFieldType, stringLength };
Vector<IntlNumberFormatField, 32> fields(stringLength, literalField);
int32_t beginIndex = 0;
int32_t endIndex = 0;
auto fieldType = ufieldpositer_next(iterator, &beginIndex, &endIndex);
while (fieldType >= 0) {
- auto size = endIndex - beginIndex;
+ size_t size = endIndex - beginIndex;
for (auto i = beginIndex; i < endIndex; ++i) {
// Only override previous value if new value is more specific.
if (fields[i].size >= size)
- fields[i] = IntlNumberFormatField(fieldType, size);
+ fields[i] = IntlNumberFormatField { fieldType, size };
}
fieldType = ufieldpositer_next(iterator, &beginIndex, &endIndex);
}
@@ -550,18 +537,14 @@
}
}
+// https://tc39.github.io/ecma402/#sec-formatnumbertoparts
JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, double value)
{
+ ASSERT(m_numberFormat);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // FormatNumberToParts (ECMA-402)
- // https://tc39.github.io/ecma402/#sec-formatnumbertoparts
- // https://tc39.github.io/ecma402/#sec-partitionnumberpattern
-
- if (!m_initializedNumberFormat)
- return throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat"_s);
-
UErrorCode status = U_ZERO_ERROR;
auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status));
if (U_FAILURE(status))
Modified: trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlNumberFormat.h 2020-04-21 04:04:10 UTC (rev 260411)
@@ -82,11 +82,12 @@
static ASCIILiteral styleString(Style);
static ASCIILiteral currencyDisplayString(CurrencyDisplay);
+ WriteBarrier<JSBoundFunction> m_boundFormat;
+ std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat;
+
String m_locale;
String m_numberingSystem;
String m_currency;
- std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat;
- WriteBarrier<JSBoundFunction> m_boundFormat;
unsigned m_minimumIntegerDigits { 1 };
unsigned m_minimumFractionDigits { 0 };
unsigned m_maximumFractionDigits { 3 };
@@ -95,22 +96,6 @@
Style m_style { Style::Decimal };
CurrencyDisplay m_currencyDisplay;
bool m_useGrouping { true };
- bool m_initializedNumberFormat { false };
-
- struct UFieldPositionIteratorDeleter {
- void operator()(UFieldPositionIterator*) const;
- };
-
- struct IntlNumberFormatField {
- int32_t type;
- int32_t size;
- IntlNumberFormatField(int32_t type, int32_t size)
- : type(type)
- , size(size)
- { }
- };
-
- static ASCIILiteral partTypeString(UNumberFormatFields, double);
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlPluralRules.cpp 2020-04-21 04:04:10 UTC (rev 260411)
@@ -88,21 +88,17 @@
Base::visitChildren(thisObject, visitor);
}
-namespace IntlPRInternal {
static Vector<String> localeData(const String&, size_t)
{
- Vector<String> data;
- return data;
+ return { };
}
-}
+// https://tc39.github.io/ecma402/#sec-initializepluralrules
void IntlPluralRules::initializePluralRules(JSGlobalObject* globalObject, JSValue locales, JSValue optionsValue)
{
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 13.1.1 InitializePluralRules (pluralRules, locales, options)
- // https://tc39.github.io/ecma402/#sec-initializepluralrules
Vector<String> requestedLocales = canonicalizeLocaleList(globalObject, locales);
RETURN_IF_EXCEPTION(scope, void());
@@ -120,7 +116,7 @@
localeOpt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);
const HashSet<String>& availableLocales = intlPluralRulesAvailableLocales();
- HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeOpt, nullptr, 0, IntlPRInternal::localeData);
+ HashMap<String, String> resolved = resolveLocale(globalObject, availableLocales, requestedLocales, localeOpt, nullptr, 0, localeData);
m_locale = resolved.get(vm.propertyNames->locale.string());
if (m_locale.isEmpty()) {
throwTypeError(globalObject, scope, "failed to initialize PluralRules due to invalid locale"_s);
@@ -183,22 +179,16 @@
throwTypeError(globalObject, scope, "failed to initialize PluralRules"_s);
return;
}
-
- m_initializedPluralRules = true;
}
+// https://tc39.es/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
JSObject* IntlPluralRules::resolvedOptions(JSGlobalObject* globalObject)
{
+ ASSERT(m_pluralRules);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 13.4.4 Intl.PluralRules.prototype.resolvedOptions ()
- // https://tc39.github.io/ecma402/#sec-intl.pluralrules.prototype.resolvedoptions
- if (UNLIKELY(!m_initializedPluralRules)) {
- throwTypeError(globalObject, scope, "Intl.PluralRules.prototype.resolvedOptions called on value that's not an object initialized as a PluralRules"_s);
- return nullptr;
- }
-
JSObject* options = constructEmptyObject(globalObject);
options->putDirect(vm, vm.propertyNames->locale, jsNontrivialString(vm, m_locale));
options->putDirect(vm, vm.propertyNames->type, jsNontrivialString(vm, m_type == UPLURAL_TYPE_ORDINAL ? "ordinal"_s : "cardinal"_s));
@@ -233,16 +223,14 @@
RELEASE_AND_RETURN(scope, options);
}
+// https://tc39.es/ecma402/#sec-resolveplural
JSValue IntlPluralRules::select(JSGlobalObject* globalObject, double value)
{
+ ASSERT(m_pluralRules);
+
VM& vm = globalObject->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- // 13.1.4 ResolvePlural (pluralRules, n)
- // https://tc39.github.io/ecma402/#sec-resolveplural
- if (!m_initializedPluralRules)
- return throwTypeError(globalObject, scope, "Intl.PluralRules.prototype.select called on value that's not an object initialized as a PluralRules"_s);
-
if (!std::isfinite(value))
return jsNontrivialString(vm, "other"_s);
Modified: trunk/Source/_javascript_Core/runtime/IntlPluralRules.h (260410 => 260411)
--- trunk/Source/_javascript_Core/runtime/IntlPluralRules.h 2020-04-21 03:23:53 UTC (rev 260410)
+++ trunk/Source/_javascript_Core/runtime/IntlPluralRules.h 2020-04-21 04:04:10 UTC (rev 260411)
@@ -70,7 +70,6 @@
void operator()(UNumberFormat*) const;
};
- bool m_initializedPluralRules { false };
std::unique_ptr<UPluralRules, UPluralRulesDeleter> m_pluralRules;
std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat;