Changeset 266033 in webkit
- Timestamp:
- Aug 22, 2020 1:16:58 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r266032 r266033 1 2020-08-22 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [ECMA-402] Implement Intl.DateTimeFormat.prototype.formatRange 4 https://bugs.webkit.org/show_bug.cgi?id=209778 5 6 Reviewed by Ross Kirsling. 7 8 test262 failures are due to either of 9 10 1. formatRangeToParts is missing 11 2. ICU version difference 12 13 * stress/intl-datetimeformat-formatrange-relevant-extensions-ja.js: Added. 14 (shouldBe): 15 (shouldThrow): 16 (vm.icuVersion): 17 * stress/intl-datetimeformat-formatrange-relevant-extensions.js: Added. 18 (shouldBe): 19 (shouldThrow): 20 * stress/intl-datetimeformat-formatrange.js: Added. 21 (shouldBe): 22 (shouldThrow): 23 (test): 24 * test262/config.yaml: 25 * test262/expectations.yaml: 26 1 27 2020-08-22 Yusuke Suzuki <ysuzuki@apple.com> 2 28 -
trunk/JSTests/test262/config.yaml
r266032 r266033 27 27 - Intl.DateTimeFormat-datetimestyle 28 28 - Intl.DateTimeFormat-dayPeriod 29 - Intl.DateTimeFormat-formatRange30 29 - Intl.DateTimeFormat-fractionalSecondDigits 31 30 - Intl.ListFormat … … 77 76 - test/built-ins/TypedArrayConstructors/internals/Set/BigInt 78 77 - test/built-ins/TypedArrayConstructors/of/BigInt 78 79 # requires ICU APIs implementation 80 # https://bugs.webkit.org/show_bug.cgi?id=213822 81 - test/intl402/DateTimeFormat/prototype/formatRangeToParts 79 82 files: 80 83 # https://bugs.webkit.org/show_bug.cgi?id=186749 -
trunk/JSTests/test262/expectations.yaml
r266032 r266033 1564 1564 default: "Test262Error: \"kn-true\" is returned in locale, but shouldn't be. Expected SameValue(«7», «-1») to be true" 1565 1565 strict mode: "Test262Error: \"kn-true\" is returned in locale, but shouldn't be. Expected SameValue(«7», «-1») to be true" 1566 test/intl402/DateTimeFormat/prototype/formatRange/en-US.js: 1567 default: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true' 1568 strict mode: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true' 1566 1569 test/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js: 1567 1570 default: 'Test262Error: Expected SameValue(«h24», «h23») to be true' -
trunk/Source/JavaScriptCore/ChangeLog
r266032 r266033 1 2020-08-22 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [ECMA-402] Implement Intl.DateTimeFormat.prototype.formatRange 4 https://bugs.webkit.org/show_bug.cgi?id=209778 5 6 Reviewed by Ross Kirsling. 7 8 This patch adds Intl.DateTimeFormat#formatRange. It takes two dates, and 9 generates formatted text which represents interval between these two dates. 10 We skip the implementation of Intl.DateTimeFormat#formatRangeToParts since 11 ICU udtitvfmt_formatToResult API is not getting stable state yet. We retrieve 12 pattern from UDateFormat, get skeleton from that pattern, and construct 13 UDateIntervalFormat from this skeleton. 14 15 * runtime/IntlDateTimeFormat.cpp: 16 (JSC::IntlDateTimeFormat::initializeDateTimeFormat): 17 (JSC::IntlDateTimeFormat::createDateIntervalFormatIfNecessary): 18 (JSC::IntlDateTimeFormat::formatRange): 19 (JSC::IntlDateTimeFormat::UDateFormatDeleter::operator() const): Deleted. 20 * runtime/IntlDateTimeFormat.h: 21 * runtime/IntlDateTimeFormatPrototype.cpp: 22 (JSC::IntlDateTimeFormatPrototypeFuncFormatRange): 23 1 24 2020-08-22 Yusuke Suzuki <ysuzuki@apple.com> 2 25 -
trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
r266031 r266033 45 45 46 46 namespace IntlDateTimeFormatInternal { 47 static constexpr bool verbose = false; 47 48 } 48 49 … … 468 469 m_hourCycle = resolved.extensions[static_cast<unsigned>(RelevantExtensionKey::Hc)]; 469 470 m_numberingSystem = resolved.extensions[static_cast<unsigned>(RelevantExtensionKey::Nu)]; 470 CString dataLocaleWithExtensions = makeString(resolved.dataLocale, "-u-ca-", m_calendar, "-nu-", m_numberingSystem).utf8(); 471 m_dataLocale = resolved.dataLocale; 472 CString dataLocaleWithExtensions = makeString(m_dataLocale, "-u-ca-", m_calendar, "-nu-", m_numberingSystem).utf8(); 471 473 472 474 JSValue tzValue = options->get(globalObject, vm.propertyNames->timeZone); … … 677 679 StringView pattern(patternBuffer.data(), patternBuffer.size()); 678 680 setFormatsFromPattern(pattern); 681 682 dataLogLnIf(IntlDateTimeFormatInternal::verbose, "locale:(", m_locale, "),dataLocale:(", dataLocaleWithExtensions, "),pattern:(", pattern, ")"); 679 683 680 684 status = U_ZERO_ERROR; … … 1026 1030 } 1027 1031 1032 UDateIntervalFormat* IntlDateTimeFormat::createDateIntervalFormatIfNecessary(JSGlobalObject* globalObject) 1033 { 1034 ASSERT(m_dateFormat); 1035 1036 VM& vm = globalObject->vm(); 1037 auto scope = DECLARE_THROW_SCOPE(vm); 1038 1039 if (m_dateIntervalFormat) 1040 return m_dateIntervalFormat.get(); 1041 1042 Vector<UChar, 32> pattern; 1043 { 1044 auto status = callBufferProducingFunction(udat_toPattern, m_dateFormat.get(), false, pattern); 1045 if (U_FAILURE(status)) { 1046 throwTypeError(globalObject, scope, "failed to initialize DateIntervalFormat"_s); 1047 return nullptr; 1048 } 1049 } 1050 1051 Vector<UChar, 32> skeleton; 1052 { 1053 auto status = callBufferProducingFunction(udatpg_getSkeleton, nullptr, pattern.data(), pattern.size(), skeleton); 1054 if (U_FAILURE(status)) { 1055 throwTypeError(globalObject, scope, "failed to initialize DateIntervalFormat"_s); 1056 return nullptr; 1057 } 1058 } 1059 1060 dataLogLnIf(IntlDateTimeFormatInternal::verbose, "interval format pattern:(", String(pattern), "),skeleton:(", String(skeleton), ")"); 1061 1062 // While the pattern is including right HourCycle patterns, UDateIntervalFormat does not follow. 1063 // We need to enforce HourCycle by setting "hc" extension if it is specified. 1064 StringBuilder localeBuilder; 1065 localeBuilder.append(m_dataLocale, "-u-ca-", m_calendar, "-nu-", m_numberingSystem); 1066 if (!m_hourCycle.isNull()) 1067 localeBuilder.append("-hc-", m_hourCycle); 1068 CString dataLocaleWithExtensions = localeBuilder.toString().utf8(); 1069 1070 UErrorCode status = U_ZERO_ERROR; 1071 StringView timeZoneView(m_timeZone); 1072 m_dateIntervalFormat = std::unique_ptr<UDateIntervalFormat, UDateIntervalFormatDeleter>(udtitvfmt_open(dataLocaleWithExtensions.data(), skeleton.data(), skeleton.size(), timeZoneView.upconvertedCharacters(), timeZoneView.length(), &status)); 1073 if (U_FAILURE(status)) { 1074 throwTypeError(globalObject, scope, "failed to initialize DateIntervalFormat"_s); 1075 return nullptr; 1076 } 1077 return m_dateIntervalFormat.get(); 1078 } 1079 1080 JSValue IntlDateTimeFormat::formatRange(JSGlobalObject* globalObject, double startDate, double endDate) 1081 { 1082 ASSERT(m_dateFormat); 1083 1084 VM& vm = globalObject->vm(); 1085 auto scope = DECLARE_THROW_SCOPE(vm); 1086 1087 // http://tc39.es/proposal-intl-DateTimeFormat-formatRange/#sec-partitiondatetimerangepattern 1088 startDate = timeClip(startDate); 1089 endDate = timeClip(endDate); 1090 if (std::isnan(startDate) || std::isnan(endDate)) { 1091 throwRangeError(globalObject, scope, "Passed date is out of range"_s); 1092 return { }; 1093 } 1094 1095 auto* dateIntervalFormat = createDateIntervalFormatIfNecessary(globalObject); 1096 RETURN_IF_EXCEPTION(scope, { }); 1097 1098 Vector<UChar, 32> buffer; 1099 auto status = callBufferProducingFunction(udtitvfmt_format, dateIntervalFormat, startDate, endDate, buffer, nullptr); 1100 if (U_FAILURE(status)) { 1101 throwTypeError(globalObject, scope, "Failed to format date interval"_s); 1102 return { }; 1103 } 1104 1105 return jsString(vm, String(buffer)); 1106 } 1107 1028 1108 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h
r266031 r266033 28 28 #include "JSObject.h" 29 29 #include <unicode/udat.h> 30 #include <unicode/udateintervalformat.h> 30 31 #include <wtf/unicode/icu/ICUHelpers.h> 31 32 … … 61 62 JSValue format(JSGlobalObject*, double value) const; 62 63 JSValue formatToParts(JSGlobalObject*, double value) const; 64 JSValue formatRange(JSGlobalObject*, double startDate, double endDate); 63 65 JSObject* resolvedOptions(JSGlobalObject*) const; 64 66 … … 73 75 static Vector<String> localeData(const String&, RelevantExtensionKey); 74 76 77 UDateIntervalFormat* createDateIntervalFormatIfNecessary(JSGlobalObject*); 78 75 79 enum class Weekday : uint8_t { None, Narrow, Short, Long }; 76 80 enum class Era : uint8_t { None, Narrow, Short, Long }; … … 82 86 enum class Second : uint8_t { None, TwoDigit, Numeric }; 83 87 enum class TimeZoneName : uint8_t { None, Short, Long }; 84 85 using UDateFormatDeleter = ICUDeleter<udat_close>;86 88 87 89 void setFormatsFromPattern(const StringView&); … … 96 98 static ASCIILiteral timeZoneNameString(TimeZoneName); 97 99 100 using UDateFormatDeleter = ICUDeleter<udat_close>; 101 using UDateIntervalFormatDeleter = ICUDeleter<udtitvfmt_close>; 102 98 103 WriteBarrier<JSBoundFunction> m_boundFormat; 99 104 std::unique_ptr<UDateFormat, UDateFormatDeleter> m_dateFormat; 105 std::unique_ptr<UDateIntervalFormat, UDateIntervalFormatDeleter> m_dateIntervalFormat; 100 106 101 107 String m_locale; 108 String m_dataLocale; 102 109 String m_calendar; 103 110 String m_numberingSystem; -
trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp
r262568 r266033 38 38 39 39 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeGetterFormat(JSGlobalObject*, CallFrame*); 40 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncFormatRange(JSGlobalObject*, CallFrame*); 40 41 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncFormatToParts(JSGlobalObject*, CallFrame*); 41 42 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncResolvedOptions(JSGlobalObject*, CallFrame*); … … 51 52 /* Source for IntlDateTimeFormatPrototype.lut.h 52 53 @begin dateTimeFormatPrototypeTable 53 format IntlDateTimeFormatPrototypeGetterFormat DontEnum|Accessor 54 formatToParts IntlDateTimeFormatPrototypeFuncFormatToParts DontEnum|Function 1 55 resolvedOptions IntlDateTimeFormatPrototypeFuncResolvedOptions DontEnum|Function 0 54 format IntlDateTimeFormatPrototypeGetterFormat DontEnum|Accessor 55 formatRange IntlDateTimeFormatPrototypeFuncFormatRange DontEnum|Function 2 56 formatToParts IntlDateTimeFormatPrototypeFuncFormatToParts DontEnum|Function 1 57 resolvedOptions IntlDateTimeFormatPrototypeFuncResolvedOptions DontEnum|Function 0 56 58 @end 57 59 */ … … 166 168 } 167 169 170 // http://tc39.es/proposal-intl-DateTimeFormat-formatRange/#sec-intl.datetimeformat.prototype.formatRange 171 EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncFormatRange(JSGlobalObject* globalObject, CallFrame* callFrame) 172 { 173 VM& vm = globalObject->vm(); 174 auto scope = DECLARE_THROW_SCOPE(vm); 175 176 IntlDateTimeFormat* dateTimeFormat = jsDynamicCast<IntlDateTimeFormat*>(vm, callFrame->thisValue()); 177 if (!dateTimeFormat) 178 return JSValue::encode(throwTypeError(globalObject, scope, "Intl.DateTimeFormat.prototype.formatRange called on value that's not an object initialized as a DateTimeFormat"_s)); 179 180 JSValue startDateValue = callFrame->argument(0); 181 JSValue endDateValue = callFrame->argument(1); 182 183 if (startDateValue.isUndefined() || endDateValue.isUndefined()) 184 return throwVMTypeError(globalObject, scope, "startDate or endDate is undefined"_s); 185 186 double startDate = startDateValue.toNumber(globalObject); 187 RETURN_IF_EXCEPTION(scope, { }); 188 double endDate = endDateValue.toNumber(globalObject); 189 RETURN_IF_EXCEPTION(scope, { }); 190 if (startDate > endDate) 191 return throwVMRangeError(globalObject, scope, "startDate is larger than endDate"_s); 192 193 RELEASE_AND_RETURN(scope, JSValue::encode(dateTimeFormat->formatRange(globalObject, startDate, endDate))); 194 } 195 168 196 EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncResolvedOptions(JSGlobalObject* globalObject, CallFrame* callFrame) 169 197 {
Note: See TracChangeset
for help on using the changeset viewer.