Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:GA
webkit2gtk3.25251
webkit2gtk3-icu52.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File webkit2gtk3-icu52.patch of Package webkit2gtk3.25251
diff -urp webkitgtk-2.36.0.icu60/Source/cmake/OptionsGTK.cmake webkitgtk-2.36.0.icu52/Source/cmake/OptionsGTK.cmake --- webkitgtk-2.36.0.icu60/Source/cmake/OptionsGTK.cmake 2022-03-29 15:02:28.892121597 -0500 +++ webkitgtk-2.36.0.icu52/Source/cmake/OptionsGTK.cmake 2022-03-28 15:11:54.570977102 -0500 @@ -14,7 +14,7 @@ find_package(Freetype 2.4.2 REQUIRED) find_package(LibGcrypt 1.6.0 REQUIRED) find_package(GLIB 2.56.4 REQUIRED COMPONENTS gio gio-unix gobject gthread gmodule) find_package(HarfBuzz 0.9.18 REQUIRED COMPONENTS ICU) -find_package(ICU 60.2 REQUIRED COMPONENTS data i18n uc) +find_package(ICU 52.1 REQUIRED COMPONENTS data i18n uc) find_package(JPEG REQUIRED) find_package(LibXml2 2.8.0 REQUIRED) find_package(PNG REQUIRED) diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/CMakeLists.txt webkitgtk-2.36.0.icu52/Source/JavaScriptCore/CMakeLists.txt --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/CMakeLists.txt 2022-02-23 02:58:52.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/CMakeLists.txt 2022-03-28 15:11:04.214708945 -0500 @@ -73,16 +73,11 @@ set(JavaScriptCore_OBJECT_LUT_SOURCES runtime/IntlDateTimeFormatPrototype.cpp runtime/IntlDisplayNamesConstructor.cpp runtime/IntlDisplayNamesPrototype.cpp - runtime/IntlListFormatConstructor.cpp - runtime/IntlListFormatPrototype.cpp - runtime/IntlLocalePrototype.cpp runtime/IntlNumberFormatConstructor.cpp runtime/IntlNumberFormatPrototype.cpp runtime/IntlObject.cpp runtime/IntlPluralRulesConstructor.cpp runtime/IntlPluralRulesPrototype.cpp - runtime/IntlRelativeTimeFormatConstructor.cpp - runtime/IntlRelativeTimeFormatPrototype.cpp runtime/IntlSegmentIteratorPrototype.cpp runtime/IntlSegmenterConstructor.cpp runtime/IntlSegmenterPrototype.cpp diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources-input.xcfilelist webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources-input.xcfilelist --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources-input.xcfilelist 2022-02-23 02:58:52.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources-input.xcfilelist 2022-03-28 15:11:04.214708945 -0500 @@ -150,16 +150,12 @@ $(PROJECT_DIR)/runtime/IntlDateTimeForma $(PROJECT_DIR)/runtime/IntlDateTimeFormatPrototype.cpp $(PROJECT_DIR)/runtime/IntlDisplayNamesConstructor.cpp $(PROJECT_DIR)/runtime/IntlDisplayNamesPrototype.cpp -$(PROJECT_DIR)/runtime/IntlListFormatConstructor.cpp -$(PROJECT_DIR)/runtime/IntlListFormatPrototype.cpp $(PROJECT_DIR)/runtime/IntlLocalePrototype.cpp $(PROJECT_DIR)/runtime/IntlNumberFormatConstructor.cpp $(PROJECT_DIR)/runtime/IntlNumberFormatPrototype.cpp $(PROJECT_DIR)/runtime/IntlObject.cpp $(PROJECT_DIR)/runtime/IntlPluralRulesConstructor.cpp $(PROJECT_DIR)/runtime/IntlPluralRulesPrototype.cpp -$(PROJECT_DIR)/runtime/IntlRelativeTimeFormatConstructor.cpp -$(PROJECT_DIR)/runtime/IntlRelativeTimeFormatPrototype.cpp $(PROJECT_DIR)/runtime/IntlSegmentIteratorPrototype.cpp $(PROJECT_DIR)/runtime/IntlSegmenterConstructor.cpp $(PROJECT_DIR)/runtime/IntlSegmenterPrototype.cpp diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources.make webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources.make --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources.make 2022-02-23 02:58:52.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources.make 2022-03-28 15:11:04.214708945 -0500 @@ -165,16 +165,12 @@ OBJECT_LUT_HEADERS = \ IntlDateTimeFormatPrototype.lut.h \ IntlDisplayNamesConstructor.lut.h \ IntlDisplayNamesPrototype.lut.h \ - IntlListFormatConstructor.lut.h \ - IntlListFormatPrototype.lut.h \ IntlLocalePrototype.lut.h \ IntlNumberFormatConstructor.lut.h \ IntlNumberFormatPrototype.lut.h \ IntlObject.lut.h \ IntlPluralRulesConstructor.lut.h \ IntlPluralRulesPrototype.lut.h \ - IntlRelativeTimeFormatConstructor.lut.h \ - IntlRelativeTimeFormatPrototype.lut.h \ IntlSegmentIteratorPrototype.lut.h \ IntlSegmenterConstructor.lut.h \ IntlSegmenterPrototype.lut.h \ diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources-output.xcfilelist webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources-output.xcfilelist --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/DerivedSources-output.xcfilelist 2022-02-23 02:58:52.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/DerivedSources-output.xcfilelist 2022-03-28 15:11:04.214708945 -0500 @@ -28,16 +28,12 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/Jav $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlDateTimeFormatPrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlDisplayNamesConstructor.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlDisplayNamesPrototype.lut.h -$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlListFormatConstructor.lut.h -$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlListFormatPrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlLocalePrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlNumberFormatConstructor.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlNumberFormatPrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlObject.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlPluralRulesConstructor.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlPluralRulesPrototype.lut.h -$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlRelativeTimeFormatConstructor.lut.h -$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlRelativeTimeFormatPrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlSegmentIteratorPrototype.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlSegmenterConstructor.lut.h $(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/IntlSegmenterPrototype.lut.h diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/Heap.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/Heap.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/Heap.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/Heap.cpp 2022-03-29 16:50:50.002745609 -0500 @@ -334,11 +334,8 @@ Heap::Heap(VM& vm, HeapType heapType) , intlCollatorHeapCellType(IsoHeapCellType::Args<IntlCollator>()) , intlDateTimeFormatHeapCellType(IsoHeapCellType::Args<IntlDateTimeFormat>()) , intlDisplayNamesHeapCellType(IsoHeapCellType::Args<IntlDisplayNames>()) - , intlListFormatHeapCellType(IsoHeapCellType::Args<IntlListFormat>()) - , intlLocaleHeapCellType(IsoHeapCellType::Args<IntlLocale>()) , intlNumberFormatHeapCellType(IsoHeapCellType::Args<IntlNumberFormat>()) , intlPluralRulesHeapCellType(IsoHeapCellType::Args<IntlPluralRules>()) - , intlRelativeTimeFormatHeapCellType(IsoHeapCellType::Args<IntlRelativeTimeFormat>()) , intlSegmentIteratorHeapCellType(IsoHeapCellType::Args<IntlSegmentIterator>()) , intlSegmenterHeapCellType(IsoHeapCellType::Args<IntlSegmenter>()) , intlSegmentsHeapCellType(IsoHeapCellType::Args<IntlSegments>()) diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/Heap.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/Heap.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/Heap.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/Heap.h 2022-03-29 17:12:52.801790710 -0500 @@ -221,11 +221,8 @@ class Heap; v(intlCollatorSpace, intlCollatorHeapCellType, IntlCollator) \ v(intlDateTimeFormatSpace, intlDateTimeFormatHeapCellType, IntlDateTimeFormat) \ v(intlDisplayNamesSpace, intlDisplayNamesHeapCellType, IntlDisplayNames) \ - v(intlListFormatSpace, intlListFormatHeapCellType, IntlListFormat) \ - v(intlLocaleSpace, intlLocaleHeapCellType, IntlLocale) \ v(intlNumberFormatSpace, intlNumberFormatHeapCellType, IntlNumberFormat) \ v(intlPluralRulesSpace, intlPluralRulesHeapCellType, IntlPluralRules) \ - v(intlRelativeTimeFormatSpace, intlRelativeTimeFormatHeapCellType, IntlRelativeTimeFormat) \ v(intlSegmentIteratorSpace, intlSegmentIteratorHeapCellType, IntlSegmentIterator) \ v(intlSegmenterSpace, intlSegmenterHeapCellType, IntlSegmenter) \ v(intlSegmentsSpace, intlSegmentsHeapCellType, IntlSegments) \ @@ -954,11 +951,8 @@ public: IsoHeapCellType intlCollatorHeapCellType; IsoHeapCellType intlDateTimeFormatHeapCellType; IsoHeapCellType intlDisplayNamesHeapCellType; - IsoHeapCellType intlListFormatHeapCellType; - IsoHeapCellType intlLocaleHeapCellType; IsoHeapCellType intlNumberFormatHeapCellType; IsoHeapCellType intlPluralRulesHeapCellType; - IsoHeapCellType intlRelativeTimeFormatHeapCellType; IsoHeapCellType intlSegmentIteratorHeapCellType; IsoHeapCellType intlSegmenterHeapCellType; IsoHeapCellType intlSegmentsHeapCellType; diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/HeapSubspaceTypes.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/HeapSubspaceTypes.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/heap/HeapSubspaceTypes.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/heap/HeapSubspaceTypes.h 2022-03-29 17:11:15.245271236 -0500 @@ -40,11 +40,8 @@ #include "IntlCollator.h" #include "IntlDateTimeFormat.h" #include "IntlDisplayNames.h" -#include "IntlListFormat.h" -#include "IntlLocale.h" #include "IntlNumberFormat.h" #include "IntlPluralRules.h" -#include "IntlRelativeTimeFormat.h" #include "IntlSegmentIterator.h" #include "IntlSegmenter.h" #include "IntlSegments.h" diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/BigIntPrototype.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/BigIntPrototype.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/BigIntPrototype.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/BigIntPrototype.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -29,7 +29,7 @@ #include "BigIntObject.h" #include "IntegrityInlines.h" -#include "IntlNumberFormatInlines.h" +#include "IntlNumberFormat.h" #include "JSBigInt.h" #include "JSCInlines.h" #include "JSCast.h" @@ -132,20 +132,13 @@ JSC_DEFINE_HOST_FUNCTION(bigIntProtoFunc VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - JSBigInt* thisValue = toThisBigIntValue(globalObject, callFrame->thisValue()); + JSBigInt* value = toThisBigIntValue(globalObject, callFrame->thisValue()); RETURN_IF_EXCEPTION(scope, { }); auto* numberFormat = IntlNumberFormat::create(vm, globalObject->numberFormatStructure()); numberFormat->initializeNumberFormat(globalObject, callFrame->argument(0), callFrame->argument(1)); - RETURN_IF_EXCEPTION(scope, { }); - - auto value = toIntlMathematicalValue(globalObject, thisValue); - RETURN_IF_EXCEPTION(scope, { }); - - if (auto number = value.tryGetDouble()) - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, number.value()))); - - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, WTFMove(value)))); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, value))); } JSC_DEFINE_HOST_FUNCTION(bigIntProtoFuncValueOf, (JSGlobalObject* globalObject, CallFrame* callFrame)) diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/CommonIdentifiers.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/CommonIdentifiers.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/CommonIdentifiers.h 2022-03-29 15:02:28.892121597 -0500 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/CommonIdentifiers.h 2022-03-28 15:11:04.214708945 -0500 @@ -42,9 +42,7 @@ macro(Function) \ macro(Infinity) \ macro(Intl) \ - macro(ListFormat) \ macro(Loader) \ - macro(Locale) \ macro(Map) \ macro(NaN) \ macro(Number) \ @@ -55,7 +53,6 @@ macro(ShadowRealm) \ macro(Reflect) \ macro(RegExp) \ - macro(RelativeTimeFormat) \ macro(RemotePlayback) \ macro(Segmenter) \ macro(Set) \ @@ -215,12 +212,10 @@ macro(resolve) \ macro(roundingIncrement) \ macro(roundingMode) \ - macro(roundingPriority) \ macro(script) \ macro(second) \ macro(seconds) \ macro(segment) \ - macro(selectRange) \ macro(sensitivity) \ macro(set) \ macro(size) \ @@ -250,7 +245,6 @@ macro(toPrecision) \ macro(toString) \ macro(toTemporalInstant) \ - macro(trailingZeroDisplay) \ macro(type) \ macro(uid) \ macro(unicode) \ diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlCollator.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlCollator.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlCollator.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlCollator.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -33,6 +33,7 @@ #include "JSCInlines.h" #include "ObjectConstructor.h" #include <wtf/HexNumber.h> +#include <unicode/ucol.h> namespace JSC { @@ -42,6 +43,12 @@ namespace IntlCollatorInternal { constexpr bool verbose = false; } +void IntlCollator::UCollatorDeleter::operator()(UCollator* collator) const +{ + if (collator) + ucol_close(collator); +} + IntlCollator* IntlCollator::create(VM& vm, Structure* structure) { IntlCollator* format = new (NotNull, allocateCell<IntlCollator>(vm)) IntlCollator(vm, structure); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlCollator.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlCollator.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlCollator.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlCollator.h 2022-03-28 15:11:04.214708945 -0500 @@ -27,9 +27,10 @@ #pragma once #include "IntlObject.h" -#include <unicode/ucol.h> #include <wtf/unicode/icu/ICUHelpers.h> +struct UCollator; + namespace JSC { enum class RelevantExtensionKey : uint8_t; @@ -92,7 +93,9 @@ private: enum class Sensitivity : uint8_t { Base, Accent, Case, Variant }; enum class CaseFirst : uint8_t { Upper, Lower, False }; - using UCollatorDeleter = ICUDeleter<ucol_close>; + struct UCollatorDeleter { + void operator()(UCollator*) const; + }; static ASCIILiteral usageString(Usage); static ASCIILiteral sensitivityString(Sensitivity); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -66,6 +66,12 @@ namespace IntlDateTimeFormatInternal { static constexpr bool verbose = false; } +void IntlDateTimeFormat::UDateFormatDeleter::operator()(UDateFormat* dateFormat) const +{ + if (dateFormat) + udat_close(dateFormat); +} + IntlDateTimeFormat* IntlDateTimeFormat::create(VM& vm, Structure* structure) { IntlDateTimeFormat* format = new (NotNull, allocateCell<IntlDateTimeFormat>(vm)) IntlDateTimeFormat(vm, structure); @@ -1293,6 +1299,7 @@ JSValue IntlDateTimeFormat::format(JSGlo return jsString(vm, String(result)); } +#if 0 static ASCIILiteral partTypeString(UDateFormatField field) { switch (field) { @@ -1420,6 +1427,7 @@ JSValue IntlDateTimeFormat::formatToPart return parts; } +#endif UDateIntervalFormat* IntlDateTimeFormat::createDateIntervalFormatIfNecessary(JSGlobalObject* globalObject) { diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormat.h 2022-03-28 15:11:04.214708945 -0500 @@ -28,7 +28,6 @@ #include "JSObject.h" #include <unicode/udat.h> -#include <wtf/unicode/icu/ICUHelpers.h> struct UDateIntervalFormat; @@ -127,7 +126,9 @@ private: static void replaceHourCycleInSkeleton(Vector<UChar, 32>&, bool hour12); static void replaceHourCycleInPattern(Vector<UChar, 32>&, HourCycle); - using UDateFormatDeleter = ICUDeleter<udat_close>; + struct UDateFormatDeleter { + void operator()(UDateFormat*) const; + }; WriteBarrier<JSBoundFunction> m_boundFormat; std::unique_ptr<UDateFormat, UDateFormatDeleter> m_dateFormat; diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -40,7 +40,6 @@ namespace JSC { static JSC_DECLARE_CUSTOM_GETTER(intlDateTimeFormatPrototypeGetterFormat); static JSC_DECLARE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncFormatRange); static JSC_DECLARE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncFormatRangeToParts); -static JSC_DECLARE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncFormatToParts); static JSC_DECLARE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncResolvedOptions); static JSC_DECLARE_HOST_FUNCTION(intlDateTimeFormatFuncFormatDateTime); @@ -56,7 +55,6 @@ const ClassInfo IntlDateTimeFormatProtot @begin dateTimeFormatPrototypeTable format intlDateTimeFormatPrototypeGetterFormat DontEnum|ReadOnly|CustomAccessor formatRange intlDateTimeFormatPrototypeFuncFormatRange DontEnum|Function 2 - formatToParts intlDateTimeFormatPrototypeFuncFormatToParts DontEnum|Function 1 resolvedOptions intlDateTimeFormatPrototypeFuncResolvedOptions DontEnum|Function 0 @end */ @@ -158,6 +156,7 @@ JSC_DEFINE_CUSTOM_GETTER(intlDateTimeFor return JSValue::encode(boundFormat); } +#if 0 JSC_DEFINE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncFormatToParts, (JSGlobalObject* globalObject, CallFrame* callFrame)) { VM& vm = globalObject->vm(); @@ -177,6 +176,7 @@ JSC_DEFINE_HOST_FUNCTION(intlDateTimeFor RELEASE_AND_RETURN(scope, JSValue::encode(dateTimeFormat->formatToParts(globalObject, value))); } +#endif // http://tc39.es/proposal-intl-DateTimeFormat-formatRange/#sec-intl.datetimeformat.prototype.formatRange JSC_DEFINE_HOST_FUNCTION(intlDateTimeFormatPrototypeFuncFormatRange, (JSGlobalObject* globalObject, CallFrame* callFrame)) diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDisplayNames.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDisplayNames.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlDisplayNames.cpp 2022-03-29 15:02:28.892121597 -0500 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlDisplayNames.cpp 2022-03-29 14:59:04.099030983 -0500 @@ -106,6 +106,7 @@ void IntlDisplayNames::initializeDisplay m_fallback = intlOption<Fallback>(globalObject, options, Identifier::fromString(vm, "fallback"), { { "code"_s, Fallback::Code }, { "none"_s, Fallback::None } }, "fallback must be either \"code\" or \"none\""_s, Fallback::Code); RETURN_IF_EXCEPTION(scope, void()); +#if HAVE(ICU_U_LOCALE_DISPLAY_NAMES) UErrorCode status = U_ZERO_ERROR; UDisplayContext contexts[] = { @@ -134,6 +135,10 @@ void IntlDisplayNames::initializeDisplay throwTypeError(globalObject, scope, "failed to initialize DisplayNames"_s); return; } +#else + throwTypeError(globalObject, scope, "Failed to initialize Intl.DisplayNames since used feature is not supported in the linked ICU version"_s); + return; +#endif } // https://tc39.es/proposal-intl-displaynames/#sec-Intl.DisplayNames.prototype.of diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -35,43 +35,26 @@ #include "JSBoundFunction.h" #include "JSCInlines.h" #include "ObjectConstructor.h" -#include <wtf/Range.h> #include <wtf/unicode/icu/ICUHelpers.h> -#ifdef U_HIDE_DRAFT_API -#undef U_HIDE_DRAFT_API -#endif -#if HAVE(ICU_U_NUMBER_FORMATTER) -#include <unicode/unumberformatter.h> -#endif -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -#include <unicode/unumberrangeformatter.h> -#endif -#define U_HIDE_DRAFT_API 1 - namespace JSC { const ClassInfo IntlNumberFormat::s_info = { "Object", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(IntlNumberFormat) }; namespace IntlNumberFormatInternal { -static constexpr bool verbose = false; +constexpr bool verbose = false; } -#if HAVE(ICU_U_NUMBER_FORMATTER) -void UNumberFormatterDeleter::operator()(UNumberFormatter* formatter) -{ - if (formatter) - unumf_close(formatter); -} -#endif +struct IntlNumberFormatField { + int32_t type; + size_t size; +}; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -void UNumberRangeFormatterDeleter::operator()(UNumberRangeFormatter* formatter) +void IntlNumberFormat::UNumberFormatDeleter::operator()(UNumberFormat* numberFormat) const { - if (formatter) - unumrf_close(formatter); + if (numberFormat) + unum_close(numberFormat); } -#endif IntlNumberFormat* IntlNumberFormat::create(VM& vm, Structure* structure) { @@ -140,7 +123,7 @@ static unsigned computeCurrencyDigits(co // 11.1.1 The abstract operation CurrencyDigits (currency) // "If the ISO 4217 currency and funds code list contains currency as an alphabetic code, // then return the minor unit value corresponding to the currency from the list; else return 2. - static constexpr std::pair<const char*, unsigned> currencyMinorUnits[] = { + std::pair<const char*, unsigned> currencyMinorUnits[] = { { "BHD", 3 }, { "BIF", 0 }, { "BYR", 0 }, @@ -174,119 +157,6 @@ static unsigned computeCurrencyDigits(co return 2; } -static std::optional<MeasureUnit> sanctionedSimpleUnitIdentifier(StringView unitIdentifier) -{ - ASSERT( - std::is_sorted(std::begin(simpleUnits), std::end(simpleUnits), - [](const MeasureUnit& a, const MeasureUnit& b) { - return WTF::codePointCompare(StringView(a.subType), StringView(b.subType)) < 0; - })); - - auto iterator = std::lower_bound(std::begin(simpleUnits), std::end(simpleUnits), unitIdentifier, - [](const MeasureUnit& unit, StringView unitIdentifier) { - return WTF::codePointCompare(StringView(unit.subType), unitIdentifier) < 0; - }); - if (iterator != std::end(simpleUnits) && iterator->subType == unitIdentifier) - return *iterator; - return std::nullopt; -} - -struct WellFormedUnit { -public: - explicit WellFormedUnit(MeasureUnit numerator) - : numerator(numerator) - { - } - - WellFormedUnit(MeasureUnit numerator, MeasureUnit denominator) - : numerator(numerator) - , denominator(denominator) - { - } - - MeasureUnit numerator; - std::optional<MeasureUnit> denominator; -}; - -static std::optional<WellFormedUnit> wellFormedUnitIdentifier(StringView unitIdentifier) -{ - // https://tc39.es/ecma402/#sec-iswellformedunitidentifier - if (auto unit = sanctionedSimpleUnitIdentifier(unitIdentifier)) - return WellFormedUnit(unit.value()); - - // If the substring "-per-" does not occur exactly once in unitIdentifier, then return false. - auto per = StringView("-per-"_s); - auto position = unitIdentifier.find(per); - if (position == WTF::notFound) - return std::nullopt; - if (unitIdentifier.find(per, position + per.length()) != WTF::notFound) - return std::nullopt; - - // If the result of IsSanctionedSimpleUnitIdentifier(numerator) is false, then return false. - auto numerator = unitIdentifier.substring(0, position); - auto numeratorUnit = sanctionedSimpleUnitIdentifier(numerator); - if (!numeratorUnit) - return std::nullopt; - - // If the result of IsSanctionedSimpleUnitIdentifier(denominator) is false, then return false. - auto denominator = unitIdentifier.substring(position + per.length()); - auto denominatorUnit = sanctionedSimpleUnitIdentifier(denominator); - if (!denominatorUnit) - return std::nullopt; - - return WellFormedUnit(numeratorUnit.value(), denominatorUnit.value()); -} - -static ASCIILiteral partTypeString(UNumberFormatFields field, IntlNumberFormat::Style style, bool sign, IntlMathematicalValue::NumberType type) -{ - switch (field) { - case UNUM_INTEGER_FIELD: - switch (type) { - case IntlMathematicalValue::NumberType::NaN: - return "nan"_s; - case IntlMathematicalValue::NumberType::Infinity: - return "infinity"_s; - case IntlMathematicalValue::NumberType::Integer: - return "integer"_s; - } - ASSERT_NOT_REACHED(); - return "unknown"_s; - case UNUM_FRACTION_FIELD: - return "fraction"_s; - case UNUM_DECIMAL_SEPARATOR_FIELD: - return "decimal"_s; - case UNUM_EXPONENT_SYMBOL_FIELD: - return "exponentSeparator"_s; - case UNUM_EXPONENT_SIGN_FIELD: - return "exponentMinusSign"_s; - case UNUM_EXPONENT_FIELD: - return "exponentInteger"_s; - case UNUM_GROUPING_SEPARATOR_FIELD: - return "group"_s; - case UNUM_CURRENCY_FIELD: - return "currency"_s; - case UNUM_PERCENT_FIELD: - // If the style is "unit", we should report as unit. - // JSTests/test262/test/intl402/NumberFormat/prototype/formatToParts/percent-en-US.js - return (style == IntlNumberFormat::Style::Unit) ? "unit"_s : "percentSign"_s; - case UNUM_SIGN_FIELD: - return sign ? "minusSign"_s : "plusSign"_s; -#if HAVE(ICU_U_NUMBER_FORMATTER) - case UNUM_MEASURE_UNIT_FIELD: - return "unit"_s; - case UNUM_COMPACT_FIELD: - return "compact"_s; -#endif - // These should not show up because there is no way to specify them in NumberFormat options. - // If they do, they don't fit well into any of known part types, so consider it an "unknown". - case UNUM_PERMILL_FIELD: - // Any newer additions to the UNumberFormatFields enum should just be considered an "unknown" part. - default: - return "unknown"_s; - } - return "unknown"_s; -} - // https://tc39.github.io/ecma402/#sec-initializenumberformat void IntlNumberFormat::initializeNumberFormat(JSGlobalObject* globalObject, JSValue locales, JSValue optionsValue) { @@ -325,7 +195,7 @@ void IntlNumberFormat::initializeNumberF m_numberingSystem = resolved.extensions[static_cast<unsigned>(RelevantExtensionKey::Nu)]; - m_style = intlOption<Style>(globalObject, options, vm.propertyNames->style, { { "decimal"_s, Style::Decimal }, { "percent"_s, Style::Percent }, { "currency"_s, Style::Currency }, { "unit"_s, Style::Unit } }, "style must be either \"decimal\", \"percent\", \"currency\", or \"unit\""_s, Style::Decimal); + m_style = intlOption<Style>(globalObject, options, vm.propertyNames->style, { { "decimal"_s, Style::Decimal }, { "percent"_s, Style::Percent }, { "currency"_s, Style::Currency } }, "style must be either \"decimal\", \"percent\", or \"currency\""_s, Style::Decimal); RETURN_IF_EXCEPTION(scope, void()); String currency = intlStringOption(globalObject, options, Identifier::fromString(vm, "currency"), { }, nullptr, nullptr); @@ -349,304 +219,51 @@ void IntlNumberFormat::initializeNumberF currencyDigits = computeCurrencyDigits(currency); } - m_currencyDisplay = intlOption<CurrencyDisplay>(globalObject, options, Identifier::fromString(vm, "currencyDisplay"), { { "code"_s, CurrencyDisplay::Code }, { "symbol"_s, CurrencyDisplay::Symbol }, { "narrowSymbol"_s, CurrencyDisplay::NarrowSymbol }, { "name"_s, CurrencyDisplay::Name } }, "currencyDisplay must be either \"code\", \"symbol\", or \"name\""_s, CurrencyDisplay::Symbol); + m_currencyDisplay = intlOption<CurrencyDisplay>(globalObject, options, Identifier::fromString(vm, "currencyDisplay"), { { "code"_s, CurrencyDisplay::Code }, { "symbol"_s, CurrencyDisplay::Symbol }, { "name"_s, CurrencyDisplay::Name } }, "currencyDisplay must be either \"code\", \"symbol\", or \"name\""_s, CurrencyDisplay::Symbol); RETURN_IF_EXCEPTION(scope, void()); - m_currencySign = intlOption<CurrencySign>(globalObject, options, Identifier::fromString(vm, "currencySign"), { { "standard"_s, CurrencySign::Standard }, { "accounting"_s, CurrencySign::Accounting } }, "currencySign must be either \"standard\" or \"accounting\""_s, CurrencySign::Standard); - RETURN_IF_EXCEPTION(scope, void()); - - String unit = intlStringOption(globalObject, options, Identifier::fromString(vm, "unit"), { }, nullptr, nullptr); - RETURN_IF_EXCEPTION(scope, void()); - std::optional<WellFormedUnit> wellFormedUnit; - if (!unit.isNull()) { - wellFormedUnit = wellFormedUnitIdentifier(unit); - if (!wellFormedUnit) { - throwRangeError(globalObject, scope, "unit is not a well-formed unit identifier"_s); - return; - } - m_unit = unit; - } else if (m_style == Style::Unit) { - throwTypeError(globalObject, scope, "unit must be a string"_s); - return; - } - - m_unitDisplay = intlOption<UnitDisplay>(globalObject, options, Identifier::fromString(vm, "unitDisplay"), { { "short"_s, UnitDisplay::Short }, { "narrow"_s, UnitDisplay::Narrow }, { "long"_s, UnitDisplay::Long } }, "unitDisplay must be either \"short\", \"narrow\", or \"long\""_s, UnitDisplay::Short); + unsigned minimumIntegerDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumIntegerDigits"), 1, 21, 1); RETURN_IF_EXCEPTION(scope, void()); + m_minimumIntegerDigits = minimumIntegerDigits; unsigned minimumFractionDigitsDefault = (m_style == Style::Currency) ? currencyDigits : 0; - unsigned maximumFractionDigitsDefault = (m_style == Style::Currency) ? currencyDigits : (m_style == Style::Percent) ? 0 : 3; - - m_notation = intlOption<IntlNotation>(globalObject, options, Identifier::fromString(vm, "notation"), { { "standard"_s, IntlNotation::Standard }, { "scientific"_s, IntlNotation::Scientific }, { "engineering"_s, IntlNotation::Engineering }, { "compact"_s, IntlNotation::Compact } }, "notation must be either \"standard\", \"scientific\", \"engineering\", or \"compact\""_s, IntlNotation::Standard); - RETURN_IF_EXCEPTION(scope, void()); - - setNumberFormatDigitOptions(globalObject, this, options, minimumFractionDigitsDefault, maximumFractionDigitsDefault, m_notation); - RETURN_IF_EXCEPTION(scope, void()); - - m_roundingIncrement = intlNumberOption(globalObject, options, vm.propertyNames->roundingIncrement, 1, 5000, 1); - RETURN_IF_EXCEPTION(scope, void()); - static constexpr const unsigned roundingIncrementCandidates[] = { - 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000 - }; - if (std::none_of(roundingIncrementCandidates, roundingIncrementCandidates + std::size(roundingIncrementCandidates), - [&](unsigned candidate) { - return candidate == m_roundingIncrement; - })) { - throwRangeError(globalObject, scope, "roundingIncrement must be one of 1, 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, 5000"_s); - return; - } - if (m_roundingIncrement != 1 && m_roundingType != IntlRoundingType::FractionDigits) { - throwRangeError(globalObject, scope, "rounding type is not fraction-digits while roundingIncrement is specified"_s); - return; - } - - m_trailingZeroDisplay = intlOption<TrailingZeroDisplay>(globalObject, options, vm.propertyNames->trailingZeroDisplay, { { "auto"_s, TrailingZeroDisplay::Auto }, { "stripIfInteger"_s, TrailingZeroDisplay::StripIfInteger } }, "trailingZeroDisplay must be either \"auto\" or \"stripIfInteger\""_s, TrailingZeroDisplay::Auto); RETURN_IF_EXCEPTION(scope, void()); - m_compactDisplay = intlOption<CompactDisplay>(globalObject, options, Identifier::fromString(vm, "compactDisplay"), { { "short"_s, CompactDisplay::Short }, { "long"_s, CompactDisplay::Long } }, "compactDisplay must be either \"short\" or \"long\""_s, CompactDisplay::Short); + unsigned minimumFractionDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumFractionDigits"), 0, 20, minimumFractionDigitsDefault); RETURN_IF_EXCEPTION(scope, void()); + m_minimumFractionDigits = minimumFractionDigits; - UseGrouping defaultUseGrouping = UseGrouping::Auto; - if (m_notation == IntlNotation::Compact) - defaultUseGrouping = UseGrouping::Min2; + unsigned maximumFractionDigitsDefault; + if (m_style == Style::Currency) + maximumFractionDigitsDefault = std::max(minimumFractionDigits, currencyDigits); + else if (m_style == Style::Percent) + maximumFractionDigitsDefault = minimumFractionDigits; + else + maximumFractionDigitsDefault = std::max(minimumFractionDigits, 3u); - m_useGrouping = intlStringOrBooleanOption<UseGrouping>(globalObject, options, Identifier::fromString(vm, "useGrouping"), UseGrouping::Always, UseGrouping::False, { { "min2"_s, UseGrouping::Min2 }, { "auto"_s, UseGrouping::Auto }, { "always"_s, UseGrouping::Always } }, "useGrouping must be either true, false, \"min2\", \"auto\", or \"always\""_s, defaultUseGrouping); + unsigned maximumFractionDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "maximumFractionDigits"), minimumFractionDigits, 20, maximumFractionDigitsDefault); RETURN_IF_EXCEPTION(scope, void()); + m_maximumFractionDigits = maximumFractionDigits; - m_signDisplay = intlOption<SignDisplay>(globalObject, options, Identifier::fromString(vm, "signDisplay"), { { "auto"_s, SignDisplay::Auto }, { "never"_s, SignDisplay::Never }, { "always"_s, SignDisplay::Always }, { "exceptZero"_s, SignDisplay::ExceptZero }, { "negative"_s, SignDisplay::Negative } }, "signDisplay must be either \"auto\", \"never\", \"always\", \"exceptZero\", or \"negative\""_s, SignDisplay::Auto); + JSValue minimumSignificantDigitsValue = options->get(globalObject, Identifier::fromString(vm, "minimumSignificantDigits")); RETURN_IF_EXCEPTION(scope, void()); - m_roundingMode = intlOption<RoundingMode>(globalObject, options, vm.propertyNames->roundingMode, { - { "ceil"_s, RoundingMode::Ceil }, - { "floor"_s, RoundingMode::Floor }, - { "expand"_s, RoundingMode::Expand }, - { "trunc"_s, RoundingMode::Trunc }, - { "halfCeil"_s, RoundingMode::HalfCeil }, - { "halfFloor"_s, RoundingMode::HalfFloor }, - { "halfExpand"_s, RoundingMode::HalfExpand }, - { "halfTrunc"_s, RoundingMode::HalfTrunc }, - { "halfEven"_s, RoundingMode::HalfEven } - }, "roundingMode must be either \"ceil\", \"floor\", \"expand\", \"trunc\", \"halfCeil\", \"halfFloor\", \"halfExpand\", \"halfTrunc\", or \"halfEven\""_s, RoundingMode::HalfExpand); + JSValue maximumSignificantDigitsValue = options->get(globalObject, Identifier::fromString(vm, "maximumSignificantDigits")); RETURN_IF_EXCEPTION(scope, void()); - CString dataLocaleWithExtensions = makeString(resolved.dataLocale, "-u-nu-", m_numberingSystem).utf8(); - dataLogLnIf(IntlNumberFormatInternal::verbose, "dataLocaleWithExtensions:(", dataLocaleWithExtensions , ")"); - - // Options are obtained. Configure formatter here. - -#if HAVE(ICU_U_NUMBER_FORMATTER) - // Constructing ICU Number Skeletons to configure UNumberFormatter. - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md - - StringBuilder skeletonBuilder; - - switch (m_roundingMode) { - case RoundingMode::Ceil: - skeletonBuilder.append("rounding-mode-ceiling"); - break; - case RoundingMode::Floor: - skeletonBuilder.append("rounding-mode-floor"); - break; - case RoundingMode::Expand: - skeletonBuilder.append("rounding-mode-up"); - break; - case RoundingMode::Trunc: - skeletonBuilder.append("rounding-mode-down"); - break; - case RoundingMode::HalfCeil: { - // Only ICU69~ supports half-ceiling. Ignore this option if linked ICU does not support it. - // https://github.com/unicode-org/icu/commit/e8dfea9bb6bb27596731173b352759e44ad06b21 - if (WTF::ICU::majorVersion() >= 69) - skeletonBuilder.append("rounding-mode-half-ceiling"); - else - skeletonBuilder.append("rounding-mode-half-up"); // Default option. - break; - } - case RoundingMode::HalfFloor: { - // Only ICU69~ supports half-ceil. Ignore this option if linked ICU does not support it. - // https://github.com/unicode-org/icu/commit/e8dfea9bb6bb27596731173b352759e44ad06b21 - if (WTF::ICU::majorVersion() >= 69) - skeletonBuilder.append("rounding-mode-half-floor"); - else - skeletonBuilder.append("rounding-mode-half-up"); // Default option. - break; - } - case RoundingMode::HalfExpand: - skeletonBuilder.append("rounding-mode-half-up"); - break; - case RoundingMode::HalfTrunc: - skeletonBuilder.append("rounding-mode-half-down"); - break; - case RoundingMode::HalfEven: - skeletonBuilder.append("rounding-mode-half-even"); - break; - } - - switch (m_style) { - case Style::Decimal: - // No skeleton is needed. - break; - case Style::Percent: - skeletonBuilder.append(" percent scale/100"); - break; - case Style::Currency: { - skeletonBuilder.append(" currency/", currency); - - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#unit-width - switch (m_currencyDisplay) { - case CurrencyDisplay::Code: - skeletonBuilder.append(" unit-width-iso-code"); - break; - case CurrencyDisplay::Symbol: - // Default option. Do not specify unit-width. - break; - case CurrencyDisplay::NarrowSymbol: - skeletonBuilder.append(" unit-width-narrow"); - break; - case CurrencyDisplay::Name: - skeletonBuilder.append(" unit-width-full-name"); - break; - } - break; - } - case Style::Unit: { - // The measure-unit stem takes one required option: the unit identifier of the unit to be formatted. - // The full unit identifier is required: both the type and the subtype (for example, length-meter). - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#unit - skeletonBuilder.append(" measure-unit/"); - auto numeratorUnit = wellFormedUnit->numerator; - skeletonBuilder.append(numeratorUnit.type, '-', numeratorUnit.subType); - if (auto denominatorUnitValue = wellFormedUnit->denominator) { - auto denominatorUnit = denominatorUnitValue.value(); - skeletonBuilder.append(" per-measure-unit/", denominatorUnit.type, '-', denominatorUnit.subType); - } - - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#unit-width - switch (m_unitDisplay) { - case UnitDisplay::Short: - skeletonBuilder.append(" unit-width-short"); - break; - case UnitDisplay::Narrow: - skeletonBuilder.append(" unit-width-narrow"); - break; - case UnitDisplay::Long: - skeletonBuilder.append(" unit-width-full-name"); - break; - } - break; - } - } - - appendNumberFormatDigitOptionsToSkeleton(this, skeletonBuilder); - - // Configure this just after precision. - // https://github.com/unicode-org/icu/blob/main/docs/userguide/format_parse/numbers/skeletons.md#trailing-zero-display - switch (m_trailingZeroDisplay) { - case TrailingZeroDisplay::Auto: - break; - case TrailingZeroDisplay::StripIfInteger: - // Only ICU69~ supports trailing zero display. Ignore this option if linked ICU does not support it. - // https://github.com/unicode-org/icu/commit/b79c299f90d4023ac237db3d0335d568bf21cd36 - if (WTF::ICU::majorVersion() >= 69) - skeletonBuilder.append("/w"); - break; - } - - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#notation - switch (m_notation) { - case IntlNotation::Standard: - break; - case IntlNotation::Scientific: - skeletonBuilder.append(" scientific"); - break; - case IntlNotation::Engineering: - skeletonBuilder.append(" engineering"); - break; - case IntlNotation::Compact: - switch (m_compactDisplay) { - case CompactDisplay::Short: - skeletonBuilder.append(" compact-short"); - break; - case CompactDisplay::Long: - skeletonBuilder.append(" compact-long"); - break; - } - break; - } - - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#sign-display - // CurrencySign's accounting is a part of SignDisplay in ICU. - bool useAccounting = (m_style == Style::Currency && m_currencySign == CurrencySign::Accounting); - switch (m_signDisplay) { - case SignDisplay::Auto: - if (useAccounting) - skeletonBuilder.append(" sign-accounting"); - else - skeletonBuilder.append(" sign-auto"); - break; - case SignDisplay::Never: - skeletonBuilder.append(" sign-never"); - break; - case SignDisplay::Always: - if (useAccounting) - skeletonBuilder.append(" sign-accounting-always"); - else - skeletonBuilder.append(" sign-always"); - break; - case SignDisplay::ExceptZero: - if (useAccounting) - skeletonBuilder.append(" sign-accounting-except-zero"); - else - skeletonBuilder.append(" sign-except-zero"); - break; - case SignDisplay::Negative: - // Only ICU69~ supports negative sign display. Ignore this option if linked ICU does not support it. - // https://github.com/unicode-org/icu/commit/1aa0dad8e06ecc99bff442dd37f6daa2d39d9a5a - if (WTF::ICU::majorVersion() >= 69) { - if (useAccounting) - skeletonBuilder.append(" sign-accounting-negative"); - else - skeletonBuilder.append(" sign-negative"); - } - break; - } - - // https://github.com/tc39/proposal-intl-numberformat-v3/issues/3 - // https://github.com/unicode-org/icu/blob/main/docs/userguide/format_parse/numbers/skeletons.md#grouping - switch (m_useGrouping) { - case UseGrouping::False: - skeletonBuilder.append(" group-off"); - break; - case UseGrouping::Min2: - skeletonBuilder.append(" group-min2"); - break; - case UseGrouping::Auto: - skeletonBuilder.append(" group-auto"); - break; - case UseGrouping::Always: - skeletonBuilder.append(" group-on-aligned"); - break; + if (!minimumSignificantDigitsValue.isUndefined() || !maximumSignificantDigitsValue.isUndefined()) { + unsigned minimumSignificantDigits = intlDefaultNumberOption(globalObject, minimumSignificantDigitsValue, Identifier::fromString(vm, "minimumSignificantDigits"), 1, 21, 1); + RETURN_IF_EXCEPTION(scope, void()); + unsigned maximumSignificantDigits = intlDefaultNumberOption(globalObject, maximumSignificantDigitsValue, Identifier::fromString(vm, "maximumSignificantDigits"), minimumSignificantDigits, 21, 21); + RETURN_IF_EXCEPTION(scope, void()); + m_minimumSignificantDigits = minimumSignificantDigits; + m_maximumSignificantDigits = maximumSignificantDigits; } - String skeleton = skeletonBuilder.toString(); - dataLogLnIf(IntlNumberFormatInternal::verbose, skeleton); - StringView skeletonView(skeleton); - auto upconverted = skeletonView.upconvertedCharacters(); - - UErrorCode status = U_ZERO_ERROR; - m_numberFormatter = std::unique_ptr<UNumberFormatter, UNumberFormatterDeleter>(unumf_openForSkeletonAndLocale(upconverted.get(), skeletonView.length(), dataLocaleWithExtensions.data(), &status)); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to initialize NumberFormat"_s); - return; - } + TriState useGrouping = intlBooleanOption(globalObject, options, Identifier::fromString(vm, "useGrouping")); + RETURN_IF_EXCEPTION(scope, void()); + m_useGrouping = useGrouping != TriState::False; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - m_numberRangeFormatter = std::unique_ptr<UNumberRangeFormatter, UNumberRangeFormatterDeleter>(unumrf_openForSkeletonWithCollapseAndIdentityFallback(upconverted.get(), skeletonView.length(), UNUM_RANGE_COLLAPSE_AUTO, UNUM_IDENTITY_FALLBACK_APPROXIMATELY, dataLocaleWithExtensions.data(), nullptr, &status)); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "failed to initialize NumberFormat"_s); - return; - } -#endif -#else UNumberFormatStyle style = UNUM_DEFAULT; switch (m_style) { case Style::Decimal: @@ -663,49 +280,19 @@ void IntlNumberFormat::initializeNumberF case CurrencyDisplay::Symbol: style = UNUM_CURRENCY; break; - case CurrencyDisplay::NarrowSymbol: - style = UNUM_CURRENCY; // Use the same option to "symbol" since linked-ICU does not support it. - break; case CurrencyDisplay::Name: style = UNUM_CURRENCY_PLURAL; break; + default: + ASSERT_NOT_REACHED(); } - switch (m_currencySign) { - case CurrencySign::Standard: - break; - case CurrencySign::Accounting: - // Ignore this case since linked ICU does not support it. - break; - } - break; - case Style::Unit: - // Ignore this case since linked ICU does not support it. - break; - } - - switch (m_notation) { - case IntlNotation::Standard: - break; - case IntlNotation::Scientific: - case IntlNotation::Engineering: - case IntlNotation::Compact: - // Ignore this case since linked ICU does not support it. - break; - } - - switch (m_signDisplay) { - case SignDisplay::Auto: - break; - case SignDisplay::Never: - case SignDisplay::Always: - case SignDisplay::ExceptZero: - case SignDisplay::Negative: - // Ignore this case since linked ICU does not support it. break; + default: + ASSERT_NOT_REACHED(); } UErrorCode status = U_ZERO_ERROR; - m_numberFormat = std::unique_ptr<UNumberFormat, ICUDeleter<unum_close>>(unum_open(style, nullptr, 0, dataLocaleWithExtensions.data(), nullptr, &status)); + m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(style, nullptr, 0, m_locale.utf8().data(), nullptr, &status)); if (U_FAILURE(status)) { throwTypeError(globalObject, scope, "failed to initialize NumberFormat"_s); return; @@ -719,531 +306,56 @@ void IntlNumberFormat::initializeNumberF } } - switch (m_roundingType) { - case IntlRoundingType::FractionDigits: + if (!m_minimumSignificantDigits) { unum_setAttribute(m_numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits); unum_setAttribute(m_numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits); unum_setAttribute(m_numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits); - break; - case IntlRoundingType::SignificantDigits: + } else { unum_setAttribute(m_numberFormat.get(), UNUM_SIGNIFICANT_DIGITS_USED, true); unum_setAttribute(m_numberFormat.get(), UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits); unum_setAttribute(m_numberFormat.get(), UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits); - break; - case IntlRoundingType::MorePrecision: - // Ignore this case since linked ICU does not support it. - break; - case IntlRoundingType::LessPrecision: - // Ignore this case since linked ICU does not support it. - break; - } - - switch (m_useGrouping) { - case UseGrouping::False: - unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, false); - break; - case UseGrouping::Min2: - // Ignore this case since linked ICU does not support it. - break; - case UseGrouping::Auto: - break; - case UseGrouping::Always: - unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, true); - break; } + unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, m_useGrouping); unum_setAttribute(m_numberFormat.get(), UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP); -#endif } // https://tc39.es/ecma402/#sec-formatnumber JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, double value) const { + ASSERT(m_numberFormat); + VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); Vector<UChar, 32> buffer; -#if HAVE(ICU_U_NUMBER_FORMATTER) - ASSERT(m_numberFormatter); - UErrorCode status = U_ZERO_ERROR; - auto formattedNumber = std::unique_ptr<UFormattedNumber, ICUDeleter<unumf_closeResult>>(unumf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - unumf_formatDouble(m_numberFormatter.get(), value, formattedNumber.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - status = callBufferProducingFunction(unumf_resultToString, formattedNumber.get(), buffer); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); -#else - ASSERT(m_numberFormat); auto status = callBufferProducingFunction(unum_formatDouble, m_numberFormat.get(), value, buffer, nullptr); if (U_FAILURE(status)) + return throwTypeError(globalObject, scope, "Failed to format a number."_s); -#endif - return jsString(vm, String(WTFMove(buffer))); + return jsString(vm, String(buffer)); } // https://tc39.es/ecma402/#sec-formatnumber -JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, IntlMathematicalValue&& value) const +JSValue IntlNumberFormat::format(JSGlobalObject* globalObject, JSBigInt* value) const { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - value.ensureNonDouble(); - const auto& string = value.getString(); - - Vector<UChar, 32> buffer; -#if HAVE(ICU_U_NUMBER_FORMATTER) - ASSERT(m_numberFormatter); - UErrorCode status = U_ZERO_ERROR; - auto formattedNumber = std::unique_ptr<UFormattedNumber, ICUDeleter<unumf_closeResult>>(unumf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s); - unumf_formatDecimal(m_numberFormatter.get(), string.data(), string.length(), formattedNumber.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s); - status = callBufferProducingFunction(unumf_resultToString, formattedNumber.get(), buffer); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s); -#else ASSERT(m_numberFormat); - auto status = callBufferProducingFunction(unum_formatDecimal, m_numberFormat.get(), string.data(), string.length(), buffer, nullptr); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s); -#endif - return jsString(vm, String(WTFMove(buffer))); -} - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -JSValue IntlNumberFormat::formatRange(JSGlobalObject* globalObject, double start, double end) const -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - ASSERT(m_numberRangeFormatter); - - if (std::isnan(start) || std::isnan(end)) - return throwRangeError(globalObject, scope, "Passed numbers are out of range"_s); - - if (end < start) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - if (isNegativeZero(end) && start >= 0) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - UErrorCode status = U_ZERO_ERROR; - auto range = std::unique_ptr<UFormattedNumberRange, ICUDeleter<unumrf_closeResult>>(unumrf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - unumrf_formatDoubleRange(m_numberRangeFormatter.get(), start, end, range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - auto* formattedValue = unumrf_resultAsValue(range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - int32_t length = 0; - const UChar* string = ufmtval_getString(formattedValue, &length, &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - return jsString(vm, String(string, length)); -} - -JSValue IntlNumberFormat::formatRange(JSGlobalObject* globalObject, IntlMathematicalValue&& start, IntlMathematicalValue&& end) const -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - ASSERT(m_numberRangeFormatter); - - if (start.numberType() == IntlMathematicalValue::NumberType::NaN || end.numberType() == IntlMathematicalValue::NumberType::NaN) - return throwRangeError(globalObject, scope, "Passed numbers are out of range"_s); - - start.ensureNonDouble(); - const auto& startString = start.getString(); - - end.ensureNonDouble(); - const auto& endString = end.getString(); - - UErrorCode status = U_ZERO_ERROR; - auto range = std::unique_ptr<UFormattedNumberRange, ICUDeleter<unumrf_closeResult>>(unumrf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - unumrf_formatDecimalRange(m_numberRangeFormatter.get(), startString.data(), startString.length(), endString.data(), endString.length(), range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - auto* formattedValue = unumrf_resultAsValue(range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - int32_t length = 0; - const UChar* string = ufmtval_getString(formattedValue, &length, &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - return jsString(vm, String(string, length)); -} -#endif - -static constexpr int32_t literalField = -1; -struct IntlNumberFormatField { - int32_t m_field; - WTF::Range<int32_t> m_range; -}; - -static Vector<IntlNumberFormatField> flattenFields(Vector<IntlNumberFormatField>&& fields, int32_t formattedStringLength) -{ - // ICU generates sequence of nested fields, but ECMA402 requires non-overlapping sequence of parts. - // This function flattens nested fields into sequence of non-overlapping parts. - // - // Formatted string: "100,000–20,000,000" - // | | | | | | | - // | B | | E F | - // | | | | - // +--C--+ +---G----+ - // +--A--+ +---D----+ - // - // Ranges ICU generates: - // A: (0, 7) UFIELD_CATEGORY_NUMBER_RANGE_SPAN startRange - // B: (3, 4) UFIELD_CATEGORY_NUMBER group "," - // C: (0, 7) UFIELD_CATEGORY_NUMBER integer - // D: (8, 18) UFIELD_CATEGORY_NUMBER_RANGE_SPAN endRange - // E: (10, 11) UFIELD_CATEGORY_NUMBER group "," - // F: (14, 15) UFIELD_CATEGORY_NUMBER group "," - // G: (8, 18) UFIELD_CATEGORY_NUMBER integer - // - // Then, we need to generate: - // A: (0, 3) startRange integer - // B: (3, 4) startRange group "," - // C: (4, 7) startRange integer - // D: (7, 8) shared literal "-" - // E: (8, 10) endRange integer - // F: (10, 11) endRange group "," - // G: (11, 14) endRange integer - // H: (14, 15) endRange group "," - // I: (15, 18) endRange integer - - std::sort(fields.begin(), fields.end(), [](auto& lhs, auto& rhs) { - if (lhs.m_range.begin() < rhs.m_range.begin()) - return true; - if (lhs.m_range.begin() > rhs.m_range.begin()) - return false; - if (lhs.m_range.end() < rhs.m_range.end()) - return false; - if (lhs.m_range.end() > rhs.m_range.end()) - return true; - return lhs.m_field < rhs.m_field; - }); - - Vector<IntlNumberFormatField> flatten; - Vector<IntlNumberFormatField> stack; - // Top-level field covers entire parts, which makes parts "literal". - stack.append(IntlNumberFormatField { literalField, { 0, formattedStringLength } }); - - unsigned cursor = 0; - int32_t begin = 0; - while (cursor < fields.size()) { - const auto& field = fields[cursor]; - - // If the new field is out of the current top-most field, roll up and insert a flatten field. - // Because the top-level field in the stack covers all index range, this condition always becomes false - // if stack size is 1. - while (stack.last().m_range.end() < field.m_range.begin()) { - if (begin < stack.last().m_range.end()) { - IntlNumberFormatField flattenField { stack.last().m_field, { begin, stack.last().m_range.end() } }; - flatten.append(flattenField); - begin = flattenField.m_range.end(); - } - stack.removeLast(); - } - ASSERT(!stack.isEmpty()); // At least, top-level field exists. - - // If the new field is starting with the same index, diving into the new field by adding it into stack. - if (begin == field.m_range.begin()) { - stack.append(field); - ++cursor; - continue; - } - - // If there is a room between the current top-most field and the new field, insert a flatten field. - if (begin < field.m_range.begin()) { - IntlNumberFormatField flattenField { stack.last().m_field, { begin, field.m_range.begin() } }; - flatten.append(flattenField); - stack.append(field); - begin = field.m_range.begin(); - ++cursor; - continue; - } - } - - // Roll up the nested field at the end of the formatted string sequence. - // For example, - // - // <------------A--------------> - // <--------B------------> - // <---C----> - // - // Then, after C finishes, we should insert remaining B and A. - while (!stack.isEmpty()) { - if (begin < stack.last().m_range.end()) { - IntlNumberFormatField flattenField { stack.last().m_field, { begin, stack.last().m_range.end() } }; - flatten.append(flattenField); - begin = flattenField.m_range.end(); - } - stack.removeLast(); - } - return flatten; -} - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) -static bool numberFieldsPracticallyEqual(const UFormattedValue* formattedValue, UErrorCode& status) -{ - auto iterator = std::unique_ptr<UConstrainedFieldPosition, ICUDeleter<ucfpos_close>>(ucfpos_open(&status)); - if (U_FAILURE(status)) - return false; - - // We only care about UFIELD_CATEGORY_NUMBER_RANGE_SPAN category. - ucfpos_constrainCategory(iterator.get(), UFIELD_CATEGORY_NUMBER_RANGE_SPAN, &status); - if (U_FAILURE(status)) - return false; - - bool hasSpan = ufmtval_nextPosition(formattedValue, iterator.get(), &status); - if (U_FAILURE(status)) - return false; - - return !hasSpan; -} - -void IntlNumberFormat::formatRangeToPartsInternal(JSGlobalObject* globalObject, Style style, IntlMathematicalValue&& start, IntlMathematicalValue&& end, const UFormattedValue* formattedValue, JSArray* parts) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - UErrorCode status = U_ZERO_ERROR; - - int32_t formattedStringLength = 0; - const UChar* formattedStringPointer = ufmtval_getString(formattedValue, &formattedStringLength, &status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return; - } - String resultString(formattedStringPointer, formattedStringLength); - - // We care multiple categories (UFIELD_CATEGORY_DATE and UFIELD_CATEGORY_DATE_INTERVAL_SPAN). - // So we do not constraint iterator. - auto iterator = std::unique_ptr<UConstrainedFieldPosition, ICUDeleter<ucfpos_close>>(ucfpos_open(&status)); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return; - } - - auto sharedString = jsNontrivialString(vm, "shared"_s); - auto startRangeString = jsNontrivialString(vm, "startRange"_s); - auto endRangeString = jsNontrivialString(vm, "endRange"_s); - auto literalString = jsNontrivialString(vm, "literal"_s); - - WTF::Range<int32_t> startRange { -1, -1 }; - WTF::Range<int32_t> endRange { -1, -1 }; - Vector<IntlNumberFormatField> fields; - - while (true) { - bool next = ufmtval_nextPosition(formattedValue, iterator.get(), &status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return; - } - if (!next) - break; - - int32_t category = ucfpos_getCategory(iterator.get(), &status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return; - } - - int32_t fieldType = ucfpos_getField(iterator.get(), &status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return; - } - - int32_t beginIndex = 0; - int32_t endIndex = 0; - ucfpos_getIndexes(iterator.get(), &beginIndex, &endIndex, &status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number interval"_s); - return; - } - - dataLogLnIf(IntlNumberFormatInternal::verbose, category, " ", fieldType, " (", beginIndex, ", ", endIndex, ")"); - - if (category != UFIELD_CATEGORY_NUMBER && category != UFIELD_CATEGORY_NUMBER_RANGE_SPAN) - continue; - if (category == UFIELD_CATEGORY_NUMBER && fieldType < 0) - continue; - - if (category == UFIELD_CATEGORY_NUMBER_RANGE_SPAN) { - // > The special field category UFIELD_CATEGORY_NUMBER_RANGE_SPAN is used to indicate which number - // > primitives came from which arguments: 0 means start, and 1 means end. The span category - // > will always occur before the corresponding fields in UFIELD_CATEGORY_NUMBER in the nextPosition() iterator. - // from ICU comment. So, field 0 is startRange, field 1 is endRange. - if (!fieldType) - startRange = WTF::Range<int32_t>(beginIndex, endIndex); - else { - ASSERT(fieldType == 1); - endRange = WTF::Range<int32_t>(beginIndex, endIndex); - } - continue; - } - - ASSERT(category == UFIELD_CATEGORY_NUMBER); - - fields.append(IntlNumberFormatField { fieldType, { beginIndex, endIndex } }); - } - - auto flatten = flattenFields(WTFMove(fields), formattedStringLength); - - auto createPart = [&] (JSString* type, int32_t beginIndex, int32_t length) { - auto sourceType = [&](int32_t index) -> JSString* { - if (startRange.contains(index)) - return startRangeString; - if (endRange.contains(index)) - return endRangeString; - return sharedString; - }; - - auto value = jsString(vm, resultString.substring(beginIndex, length)); - JSObject* part = constructEmptyObject(globalObject); - part->putDirect(vm, vm.propertyNames->type, type); - part->putDirect(vm, vm.propertyNames->value, value); - part->putDirect(vm, vm.propertyNames->source, sourceType(beginIndex)); - return part; - }; - - for (auto& field : flatten) { - bool sign = false; - IntlMathematicalValue::NumberType numberType = start.numberType(); - if (startRange.contains(field.m_range.begin())) { - numberType = start.numberType(); - sign = start.sign(); - } else { - numberType = end.numberType(); - sign = end.sign(); - } - auto fieldType = field.m_field; - auto partType = fieldType == literalField ? literalString : jsString(vm, partTypeString(UNumberFormatFields(fieldType), style, sign, numberType)); - JSObject* part = createPart(partType, field.m_range.begin(), field.m_range.distance()); - parts->push(globalObject, part); - RETURN_IF_EXCEPTION(scope, void()); - } -} - -JSValue IntlNumberFormat::formatRangeToParts(JSGlobalObject* globalObject, double start, double end) const -{ VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - ASSERT(m_numberRangeFormatter); - - if (std::isnan(start) || std::isnan(end)) - return throwRangeError(globalObject, scope, "Passed numbers are out of range"_s); - - if (end < start) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - if (isNegativeZero(end) && start >= 0) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - UErrorCode status = U_ZERO_ERROR; - auto range = std::unique_ptr<UFormattedNumberRange, ICUDeleter<unumrf_closeResult>>(unumrf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - unumrf_formatDoubleRange(m_numberRangeFormatter.get(), start, end, range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - auto* formattedValue = unumrf_resultAsValue(range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - bool equal = numberFieldsPracticallyEqual(formattedValue, status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return { }; - } - - if (equal) - RELEASE_AND_RETURN(scope, formatToParts(globalObject, start, jsNontrivialString(vm, "shared"_s))); - - JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); - if (!parts) { - throwOutOfMemoryError(globalObject, scope); - return { }; - } - - formatRangeToPartsInternal(globalObject, m_style, IntlMathematicalValue(start), IntlMathematicalValue(end), formattedValue, parts); + auto string = value->toString(globalObject, 10); RETURN_IF_EXCEPTION(scope, { }); - return parts; -} - -JSValue IntlNumberFormat::formatRangeToParts(JSGlobalObject* globalObject, IntlMathematicalValue&& start, IntlMathematicalValue&& end) const -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - ASSERT(m_numberRangeFormatter); - - if (start.numberType() == IntlMathematicalValue::NumberType::NaN || end.numberType() == IntlMathematicalValue::NumberType::NaN) - return throwRangeError(globalObject, scope, "Passed numbers are out of range"_s); - - start.ensureNonDouble(); - const auto& startString = start.getString(); - - end.ensureNonDouble(); - const auto& endString = end.getString(); + ASSERT(string.is8Bit() && string.isAllASCII()); + auto* rawString = reinterpret_cast<const char*>(string.characters8()); - UErrorCode status = U_ZERO_ERROR; - auto range = std::unique_ptr<UFormattedNumberRange, ICUDeleter<unumrf_closeResult>>(unumrf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - unumrf_formatDecimalRange(m_numberRangeFormatter.get(), startString.data(), startString.length(), endString.data(), endString.length(), range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - auto* formattedValue = unumrf_resultAsValue(range.get(), &status); + Vector<UChar, 32> buffer; + auto status = callBufferProducingFunction(unum_formatDecimal, m_numberFormat.get(), rawString, string.length(), buffer, nullptr); if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a range"_s); - - bool equal = numberFieldsPracticallyEqual(formattedValue, status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to format number range"_s); - return { }; - } - - if (equal) - RELEASE_AND_RETURN(scope, formatToParts(globalObject, WTFMove(start), jsNontrivialString(vm, "shared"_s))); - - JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); - if (!parts) { - throwOutOfMemoryError(globalObject, scope); - return { }; - } - - formatRangeToPartsInternal(globalObject, m_style, WTFMove(start), WTFMove(end), formattedValue, parts); - RETURN_IF_EXCEPTION(scope, { }); + return throwTypeError(globalObject, scope, "Failed to format a BigInt."_s); - return parts; + return jsString(vm, String(buffer)); } -#endif ASCIILiteral IntlNumberFormat::styleString(Style style) { @@ -1254,8 +366,6 @@ ASCIILiteral IntlNumberFormat::styleStri return "percent"_s; case Style::Currency: return "currency"_s; - case Style::Unit: - return "unit"_s; } ASSERT_NOT_REACHED(); return ASCIILiteral::null(); @@ -1268,8 +378,6 @@ ASCIILiteral IntlNumberFormat::currencyD return "code"_s; case CurrencyDisplay::Symbol: return "symbol"_s; - case CurrencyDisplay::NarrowSymbol: - return "narrowSymbol"_s; case CurrencyDisplay::Name: return "name"_s; } @@ -1277,146 +385,6 @@ ASCIILiteral IntlNumberFormat::currencyD return ASCIILiteral::null(); } -ASCIILiteral IntlNumberFormat::notationString(IntlNotation notation) -{ - switch (notation) { - case IntlNotation::Standard: - return "standard"_s; - case IntlNotation::Scientific: - return "scientific"_s; - case IntlNotation::Engineering: - return "engineering"_s; - case IntlNotation::Compact: - return "compact"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::currencySignString(CurrencySign currencySign) -{ - switch (currencySign) { - case CurrencySign::Standard: - return "standard"_s; - case CurrencySign::Accounting: - return "accounting"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::unitDisplayString(UnitDisplay unitDisplay) -{ - switch (unitDisplay) { - case UnitDisplay::Short: - return "short"_s; - case UnitDisplay::Narrow: - return "narrow"_s; - case UnitDisplay::Long: - return "long"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::compactDisplayString(CompactDisplay compactDisplay) -{ - switch (compactDisplay) { - case CompactDisplay::Short: - return "short"_s; - case CompactDisplay::Long: - return "long"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::signDisplayString(SignDisplay signDisplay) -{ - switch (signDisplay) { - case SignDisplay::Auto: - return "auto"_s; - case SignDisplay::Never: - return "never"_s; - case SignDisplay::Always: - return "always"_s; - case SignDisplay::ExceptZero: - return "exceptZero"_s; - case SignDisplay::Negative: - return "negative"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::roundingModeString(RoundingMode roundingMode) -{ - switch (roundingMode) { - case RoundingMode::Ceil: - return "ceil"_s; - case RoundingMode::Floor: - return "floor"_s; - case RoundingMode::Expand: - return "expand"_s; - case RoundingMode::Trunc: - return "trunc"_s; - case RoundingMode::HalfCeil: - return "halfCeil"_s; - case RoundingMode::HalfFloor: - return "halfFloor"_s; - case RoundingMode::HalfExpand: - return "halfExpand"_s; - case RoundingMode::HalfTrunc: - return "halfTrunc"_s; - case RoundingMode::HalfEven: - return "halfEven"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::trailingZeroDisplayString(TrailingZeroDisplay trailingZeroDisplay) -{ - switch (trailingZeroDisplay) { - case TrailingZeroDisplay::Auto: - return "auto"_s; - case TrailingZeroDisplay::StripIfInteger: - return "stripIfInteger"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -ASCIILiteral IntlNumberFormat::roundingPriorityString(IntlRoundingType roundingType) -{ - switch (roundingType) { - case IntlRoundingType::FractionDigits: - case IntlRoundingType::SignificantDigits: - return "auto"_s; - case IntlRoundingType::MorePrecision: - return "morePrecision"_s; - case IntlRoundingType::LessPrecision: - return "lessPrecision"_s; - } - ASSERT_NOT_REACHED(); - return ASCIILiteral::null(); -} - -JSValue IntlNumberFormat::useGroupingValue(VM& vm, UseGrouping useGrouping) -{ - switch (useGrouping) { - case UseGrouping::False: - return jsBoolean(false); - case UseGrouping::Min2: - return jsNontrivialString(vm, "min2"_s); - case UseGrouping::Auto: - return jsNontrivialString(vm, "auto"_s); - case UseGrouping::Always: - return jsNontrivialString(vm, "always"_s); - } - return jsUndefined(); -} - // https://tc39.es/ecma402/#sec-intl.numberformat.prototype.resolvedoptions JSObject* IntlNumberFormat::resolvedOptions(JSGlobalObject* globalObject) const { @@ -1425,47 +393,19 @@ JSObject* IntlNumberFormat::resolvedOpti options->putDirect(vm, vm.propertyNames->locale, jsString(vm, m_locale)); options->putDirect(vm, vm.propertyNames->numberingSystem, jsString(vm, m_numberingSystem)); options->putDirect(vm, vm.propertyNames->style, jsNontrivialString(vm, styleString(m_style))); - switch (m_style) { - case Style::Decimal: - case Style::Percent: - break; - case Style::Currency: + if (m_style == Style::Currency) { options->putDirect(vm, Identifier::fromString(vm, "currency"), jsNontrivialString(vm, m_currency)); options->putDirect(vm, Identifier::fromString(vm, "currencyDisplay"), jsNontrivialString(vm, currencyDisplayString(m_currencyDisplay))); - options->putDirect(vm, Identifier::fromString(vm, "currencySign"), jsNontrivialString(vm, currencySignString(m_currencySign))); - break; - case Style::Unit: - options->putDirect(vm, Identifier::fromString(vm, "unit"), jsNontrivialString(vm, m_unit)); - options->putDirect(vm, Identifier::fromString(vm, "unitDisplay"), jsNontrivialString(vm, unitDisplayString(m_unitDisplay))); - break; } options->putDirect(vm, vm.propertyNames->minimumIntegerDigits, jsNumber(m_minimumIntegerDigits)); - switch (m_roundingType) { - case IntlRoundingType::FractionDigits: - options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); - options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); - break; - case IntlRoundingType::SignificantDigits: - options->putDirect(vm, vm.propertyNames->minimumSignificantDigits, jsNumber(m_minimumSignificantDigits)); - options->putDirect(vm, vm.propertyNames->maximumSignificantDigits, jsNumber(m_maximumSignificantDigits)); - break; - case IntlRoundingType::MorePrecision: - case IntlRoundingType::LessPrecision: - options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); - options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); + options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); + options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); + if (m_minimumSignificantDigits) { + ASSERT(m_maximumSignificantDigits); options->putDirect(vm, vm.propertyNames->minimumSignificantDigits, jsNumber(m_minimumSignificantDigits)); options->putDirect(vm, vm.propertyNames->maximumSignificantDigits, jsNumber(m_maximumSignificantDigits)); - break; } - options->putDirect(vm, Identifier::fromString(vm, "useGrouping"), useGroupingValue(vm, m_useGrouping)); - options->putDirect(vm, Identifier::fromString(vm, "notation"), jsNontrivialString(vm, notationString(m_notation))); - if (m_notation == IntlNotation::Compact) - options->putDirect(vm, Identifier::fromString(vm, "compactDisplay"), jsNontrivialString(vm, compactDisplayString(m_compactDisplay))); - options->putDirect(vm, Identifier::fromString(vm, "signDisplay"), jsNontrivialString(vm, signDisplayString(m_signDisplay))); - options->putDirect(vm, vm.propertyNames->roundingMode, jsNontrivialString(vm, roundingModeString(m_roundingMode))); - options->putDirect(vm, vm.propertyNames->roundingIncrement, jsNumber(m_roundingIncrement)); - options->putDirect(vm, vm.propertyNames->trailingZeroDisplay, jsNontrivialString(vm, trailingZeroDisplayString(m_trailingZeroDisplay))); - options->putDirect(vm, vm.propertyNames->roundingPriority, jsNontrivialString(vm, roundingPriorityString(m_roundingType))); + options->putDirect(vm, Identifier::fromString(vm, "useGrouping"), jsBoolean(m_useGrouping)); return options; } @@ -1474,141 +414,112 @@ void IntlNumberFormat::setBoundFormat(VM m_boundFormat.set(vm, this, format); } -void IntlNumberFormat::formatToPartsInternal(JSGlobalObject* globalObject, Style style, bool sign, IntlMathematicalValue::NumberType numberType, const String& formatted, IntlFieldIterator& iterator, JSArray* parts, JSString* sourceType, JSString* unit) +static ASCIILiteral partTypeString(UNumberFormatFields field, double value) +{ + switch (field) { + case UNUM_INTEGER_FIELD: + if (std::isnan(value)) + return "nan"_s; + if (!std::isfinite(value)) + return "infinity"_s; + return "integer"_s; + case UNUM_FRACTION_FIELD: + return "fraction"_s; + case UNUM_DECIMAL_SEPARATOR_FIELD: + return "decimal"_s; + case UNUM_GROUPING_SEPARATOR_FIELD: + return "group"_s; + case UNUM_CURRENCY_FIELD: + return "currency"_s; + case UNUM_PERCENT_FIELD: + return "percentSign"_s; + case UNUM_SIGN_FIELD: + return value < 0 ? "minusSign"_s : "plusSign"_s; + // These should not show up because there is no way to specify them in NumberFormat options. + // If they do, they don't fit well into any of known part types, so consider it an "unknown". + case UNUM_PERMILL_FIELD: + case UNUM_EXPONENT_SYMBOL_FIELD: + case UNUM_EXPONENT_SIGN_FIELD: + case UNUM_EXPONENT_FIELD: + // Any newer additions to the UNumberFormatFields enum should just be considered an "unknown" part. + default: + return "unknown"_s; + } + return "unknown"_s; +} + +#if 0 +void IntlNumberFormat::formatToPartsInternal(JSGlobalObject* globalObject, double value, const String& formatted, UFieldPositionIterator* iterator, JSArray* parts, JSString* unit) { VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); auto stringLength = formatted.length(); - Vector<IntlNumberFormatField> fields; - - while (true) { - int32_t beginIndex = 0; - int32_t endIndex = 0; - UErrorCode status = U_ZERO_ERROR; - int32_t fieldType = iterator.next(beginIndex, endIndex, status); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "Failed to iterate field position iterator"_s); - return; + int32_t literalFieldType = -1; + 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) { + 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 }; } - if (fieldType < 0) - break; - - fields.append(IntlNumberFormatField { fieldType, { beginIndex, endIndex } }); + fieldType = ufieldpositer_next(iterator, &beginIndex, &endIndex); } - auto flatten = flattenFields(WTFMove(fields), stringLength); - auto literalString = jsNontrivialString(vm, "literal"_s); Identifier unitName; if (unit) unitName = Identifier::fromString(vm, "unit"); - for (auto& field : flatten) { - auto fieldType = field.m_field; - auto partType = fieldType == literalField ? literalString : jsString(vm, partTypeString(UNumberFormatFields(fieldType), style, sign, numberType)); - auto partValue = jsSubstring(vm, formatted, field.m_range.begin(), field.m_range.distance()); + size_t currentIndex = 0; + while (currentIndex < stringLength) { + auto startIndex = currentIndex; + auto fieldType = fields[currentIndex].type; + while (currentIndex < stringLength && fields[currentIndex].type == fieldType) + ++currentIndex; + auto partType = fieldType == literalFieldType ? literalString : jsString(vm, partTypeString(UNumberFormatFields(fieldType), value)); + auto partValue = jsSubstring(vm, formatted, startIndex, currentIndex - startIndex); JSObject* part = constructEmptyObject(globalObject); part->putDirect(vm, vm.propertyNames->type, partType); part->putDirect(vm, vm.propertyNames->value, partValue); if (unit) part->putDirect(vm, unitName, unit); - if (sourceType) - part->putDirect(vm, vm.propertyNames->source, sourceType); parts->push(globalObject, part); RETURN_IF_EXCEPTION(scope, void()); } } // https://tc39.github.io/ecma402/#sec-formatnumbertoparts -JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, double value, JSString* sourceType) const +JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, double value) const { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - UErrorCode status = U_ZERO_ERROR; - auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to open field position iterator"_s); - - Vector<UChar, 32> result; -#if HAVE(ICU_U_NUMBER_FORMATTER) - ASSERT(m_numberFormatter); - auto formattedNumber = std::unique_ptr<UFormattedNumber, ICUDeleter<unumf_closeResult>>(unumf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - unumf_formatDouble(m_numberFormatter.get(), value, formattedNumber.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - status = callBufferProducingFunction(unumf_resultToString, formattedNumber.get(), result); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - unumf_resultGetAllFieldPositions(formattedNumber.get(), fieldItr.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - IntlFieldIterator iterator(*fieldItr.get()); -#else ASSERT(m_numberFormat); - status = callBufferProducingFunction(unum_formatDoubleForFields, m_numberFormat.get(), value, result, fieldItr.get()); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to format a number."_s); - IntlFieldIterator iterator(*fieldItr.get()); -#endif - - auto resultString = String(WTFMove(result)); - - JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); - if (!parts) - return throwOutOfMemoryError(globalObject, scope); - - formatToPartsInternal(globalObject, m_style, std::signbit(value), IntlMathematicalValue::numberTypeFromDouble(value), resultString, iterator, parts, sourceType, nullptr); - RETURN_IF_EXCEPTION(scope, { }); - - return parts; -} -#if HAVE(ICU_U_NUMBER_FORMATTER) -JSValue IntlNumberFormat::formatToParts(JSGlobalObject* globalObject, IntlMathematicalValue&& value, JSString* sourceType) const -{ VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); - value.ensureNonDouble(); - const auto& string = value.getString(); - UErrorCode status = U_ZERO_ERROR; auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status)); if (U_FAILURE(status)) return throwTypeError(globalObject, scope, "failed to open field position iterator"_s); Vector<UChar, 32> result; - ASSERT(m_numberFormatter); - auto formattedNumber = std::unique_ptr<UFormattedNumber, ICUDeleter<unumf_closeResult>>(unumf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - - unumf_formatDecimal(m_numberFormatter.get(), string.data(), string.length(), formattedNumber.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - - status = callBufferProducingFunction(unumf_resultToString, formattedNumber.get(), result); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - - unumf_resultGetAllFieldPositions(formattedNumber.get(), fieldItr.get(), &status); + status = callBufferProducingFunction(unum_formatDoubleForFields, m_numberFormat.get(), value, result, fieldItr.get()); if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "Failed to format a number."_s); - - IntlFieldIterator iterator(*fieldItr.get()); + return throwTypeError(globalObject, scope, "failed to format a number."_s); - auto resultString = String(WTFMove(result)); + auto resultString = String(result); JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); if (!parts) return throwOutOfMemoryError(globalObject, scope); - formatToPartsInternal(globalObject, m_style, value.sign(), value.numberType(), resultString, iterator, parts, sourceType, nullptr); + formatToPartsInternal(globalObject, value, resultString, fieldItr.get(), parts); RETURN_IF_EXCEPTION(scope, { }); return parts; diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormat.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormat.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormat.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormat.h 2022-03-28 15:11:04.214708945 -0500 @@ -28,130 +28,13 @@ #pragma once #include "JSObject.h" -#include "MathCommon.h" -#include "TemporalObject.h" #include <unicode/unum.h> -#include <wtf/unicode/icu/ICUHelpers.h> - -#if !defined(HAVE_ICU_U_NUMBER_FORMATTER) -// UNUM_COMPACT_FIELD and UNUM_MEASURE_UNIT_FIELD are available after ICU 64. -#if U_ICU_VERSION_MAJOR_NUM >= 64 -#define HAVE_ICU_U_NUMBER_FORMATTER 1 -#endif -#endif - -#if !defined(HAVE_ICU_U_NUMBER_RANGE_FORMATTER) -#if U_ICU_VERSION_MAJOR_NUM >= 68 -#define HAVE_ICU_U_NUMBER_RANGE_FORMATTER 1 -#endif -#endif - -#if !defined(HAVE_ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) -#if U_ICU_VERSION_MAJOR_NUM >= 69 -#define HAVE_ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS 1 -#endif -#endif - -struct UFormattedValue; -struct UNumberFormatter; -struct UNumberRangeFormatter; namespace JSC { -class IntlFieldIterator; class JSBoundFunction; enum class RelevantExtensionKey : uint8_t; -enum class IntlRoundingType : uint8_t { FractionDigits, SignificantDigits, MorePrecision, LessPrecision }; -enum class IntlRoundingPriority : uint8_t { Auto, MorePrecision, LessPrecision }; -enum class IntlNotation : uint8_t { Standard, Scientific, Engineering, Compact }; -template<typename IntlType> void setNumberFormatDigitOptions(JSGlobalObject*, IntlType*, JSObject*, unsigned minimumFractionDigitsDefault, unsigned maximumFractionDigitsDefault, IntlNotation); -template<typename IntlType> void appendNumberFormatDigitOptionsToSkeleton(IntlType*, StringBuilder&); - -#if HAVE(ICU_U_NUMBER_FORMATTER) -struct UNumberFormatterDeleter { - JS_EXPORT_PRIVATE void operator()(UNumberFormatter*); -}; -#endif - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -struct UNumberRangeFormatterDeleter { - JS_EXPORT_PRIVATE void operator()(UNumberRangeFormatter*); -}; -#endif - -class IntlMathematicalValue { - WTF_MAKE_FAST_ALLOCATED(IntlMathematicalValue); -public: - enum class NumberType { Integer, Infinity, NaN, }; - using Value = std::variant<double, CString>; - - IntlMathematicalValue() = default; - - explicit IntlMathematicalValue(double value) - : m_numberType(numberTypeFromDouble(value)) - , m_sign(std::signbit(value)) - , m_value(value) - { } - - explicit IntlMathematicalValue(NumberType numberType, bool sign, CString value) - : m_numberType(numberType) - , m_sign(sign) - , m_value(value) - { - } - - void ensureNonDouble() - { - if (std::holds_alternative<double>(m_value)) { - switch (m_numberType) { - case NumberType::Integer: { - double value = std::get<double>(m_value); - if (isNegativeZero(value)) - m_value = CString("-0"); - else - m_value = String::number(value).ascii(); - break; - } - case NumberType::NaN: - m_value = CString("nan"); - break; - case NumberType::Infinity: - m_value = CString(m_sign ? "-infinity" : "infinity"); - break; - } - } - } - - NumberType numberType() const { return m_numberType; } - bool sign() const { return m_sign; } - std::optional<double> tryGetDouble() const - { - if (std::holds_alternative<double>(m_value)) - return std::get<double>(m_value); - return std::nullopt; - } - const CString& getString() const - { - ASSERT(std::holds_alternative<CString>(m_value)); - return std::get<CString>(m_value); - } - - static NumberType numberTypeFromDouble(double value) - { - if (std::isnan(value)) - return NumberType::NaN; - if (!std::isfinite(value)) - return NumberType::Infinity; - return NumberType::Integer; - } - -private: - NumberType m_numberType { NumberType::Integer }; - bool m_sign { false }; - Value m_value { 0.0 }; -}; - class IntlNumberFormat final : public JSNonFinalObject { public: using Base = JSNonFinalObject; @@ -176,42 +59,15 @@ public: void initializeNumberFormat(JSGlobalObject*, JSValue locales, JSValue optionsValue); JSValue format(JSGlobalObject*, double) const; - JSValue format(JSGlobalObject*, IntlMathematicalValue&&) const; - JSValue formatToParts(JSGlobalObject*, double, JSString* sourceType = nullptr) const; -#if HAVE(ICU_U_NUMBER_FORMATTER) - JSValue formatToParts(JSGlobalObject*, IntlMathematicalValue&&, JSString* sourceType = nullptr) const; -#endif + JSValue format(JSGlobalObject*, JSBigInt*) const; JSObject* resolvedOptions(JSGlobalObject*) const; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - JSValue formatRange(JSGlobalObject*, double, double) const; - JSValue formatRange(JSGlobalObject*, IntlMathematicalValue&&, IntlMathematicalValue&&) const; -#endif - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) - JSValue formatRangeToParts(JSGlobalObject*, double, double) const; - JSValue formatRangeToParts(JSGlobalObject*, IntlMathematicalValue&&, IntlMathematicalValue&&) const; -#endif - JSBoundFunction* boundFormat() const { return m_boundFormat.get(); } void setBoundFormat(VM&, JSBoundFunction*); - enum class Style : uint8_t { Decimal, Percent, Currency, Unit }; - - static void formatToPartsInternal(JSGlobalObject*, Style, bool sign, IntlMathematicalValue::NumberType, const String& formatted, IntlFieldIterator&, JSArray*, JSString* sourceType, JSString* unit); - static void formatRangeToPartsInternal(JSGlobalObject*, Style, IntlMathematicalValue&&, IntlMathematicalValue&&, const UFormattedValue*, JSArray*); - - template<typename IntlType> - friend void setNumberFormatDigitOptions(JSGlobalObject*, IntlType*, JSObject*, unsigned minimumFractionDigitsDefault, unsigned maximumFractionDigitsDefault, IntlNotation); - template<typename IntlType> - friend void appendNumberFormatDigitOptionsToSkeleton(IntlType*, StringBuilder&); - - static ASCIILiteral notationString(IntlNotation); static IntlNumberFormat* unwrapForOldFunctions(JSGlobalObject*, JSValue); - static ASCIILiteral roundingPriorityString(IntlRoundingType); - private: IntlNumberFormat(VM&, Structure*); void finishCreation(VM&); @@ -219,55 +75,30 @@ private: static Vector<String> localeData(const String&, RelevantExtensionKey); - enum class CurrencyDisplay : uint8_t { Code, Symbol, NarrowSymbol, Name }; - enum class CurrencySign : uint8_t { Standard, Accounting }; - enum class UnitDisplay : uint8_t { Short, Narrow, Long }; - enum class CompactDisplay : uint8_t { Short, Long }; - enum class SignDisplay : uint8_t { Auto, Never, Always, ExceptZero, Negative }; - enum class TrailingZeroDisplay : uint8_t { Auto, StripIfInteger }; - enum class UseGrouping : uint8_t { False, Min2, Auto, Always }; + enum class Style : uint8_t { Decimal, Percent, Currency }; + enum class CurrencyDisplay : uint8_t { Code, Symbol, Name }; + + struct UNumberFormatDeleter { + void operator()(UNumberFormat*) const; + }; static ASCIILiteral styleString(Style); static ASCIILiteral currencyDisplayString(CurrencyDisplay); - static ASCIILiteral currencySignString(CurrencySign); - static ASCIILiteral unitDisplayString(UnitDisplay); - static ASCIILiteral compactDisplayString(CompactDisplay); - static ASCIILiteral signDisplayString(SignDisplay); - static ASCIILiteral roundingModeString(RoundingMode); - static ASCIILiteral trailingZeroDisplayString(TrailingZeroDisplay); - static JSValue useGroupingValue(VM&, UseGrouping); WriteBarrier<JSBoundFunction> m_boundFormat; -#if HAVE(ICU_U_NUMBER_FORMATTER) - std::unique_ptr<UNumberFormatter, UNumberFormatterDeleter> m_numberFormatter; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - std::unique_ptr<UNumberRangeFormatter, UNumberRangeFormatterDeleter> m_numberRangeFormatter; -#endif -#else - std::unique_ptr<UNumberFormat, ICUDeleter<unum_close>> m_numberFormat; -#endif + std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat; String m_locale; String m_numberingSystem; String m_currency; - String m_unit; unsigned m_minimumIntegerDigits { 1 }; unsigned m_minimumFractionDigits { 0 }; unsigned m_maximumFractionDigits { 3 }; unsigned m_minimumSignificantDigits { 0 }; unsigned m_maximumSignificantDigits { 0 }; - unsigned m_roundingIncrement { 1 }; Style m_style { Style::Decimal }; CurrencyDisplay m_currencyDisplay; - CurrencySign m_currencySign; - UnitDisplay m_unitDisplay; - CompactDisplay m_compactDisplay; - IntlNotation m_notation { IntlNotation::Standard }; - SignDisplay m_signDisplay; - TrailingZeroDisplay m_trailingZeroDisplay { TrailingZeroDisplay::Auto }; - UseGrouping m_useGrouping { UseGrouping::Always }; - RoundingMode m_roundingMode { RoundingMode::HalfExpand }; - IntlRoundingType m_roundingType { IntlRoundingType::FractionDigits }; + bool m_useGrouping { true }; }; } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatInlines.h 2022-03-28 15:11:04.214708945 -0500 @@ -29,245 +29,13 @@ #include "IntlNumberFormat.h" #include "IntlObjectInlines.h" #include "JSGlobalObject.h" -#include "JSGlobalObjectFunctions.h" namespace JSC { -template<typename IntlType> -void setNumberFormatDigitOptions(JSGlobalObject* globalObject, IntlType* intlInstance, JSObject* options, unsigned minimumFractionDigitsDefault, unsigned maximumFractionDigitsDefault, IntlNotation notation) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - unsigned minimumIntegerDigits = intlNumberOption(globalObject, options, vm.propertyNames->minimumIntegerDigits, 1, 21, 1); - RETURN_IF_EXCEPTION(scope, void()); - - JSValue minimumFractionDigitsValue = jsUndefined(); - JSValue maximumFractionDigitsValue = jsUndefined(); - JSValue minimumSignificantDigitsValue = jsUndefined(); - JSValue maximumSignificantDigitsValue = jsUndefined(); - if (options) { - minimumFractionDigitsValue = options->get(globalObject, vm.propertyNames->minimumFractionDigits); - RETURN_IF_EXCEPTION(scope, void()); - - maximumFractionDigitsValue = options->get(globalObject, vm.propertyNames->maximumFractionDigits); - RETURN_IF_EXCEPTION(scope, void()); - - minimumSignificantDigitsValue = options->get(globalObject, vm.propertyNames->minimumSignificantDigits); - RETURN_IF_EXCEPTION(scope, void()); - - maximumSignificantDigitsValue = options->get(globalObject, vm.propertyNames->maximumSignificantDigits); - RETURN_IF_EXCEPTION(scope, void()); - } - - intlInstance->m_minimumIntegerDigits = minimumIntegerDigits; - - IntlRoundingPriority roundingPriority = intlOption<IntlRoundingPriority>(globalObject, options, vm.propertyNames->roundingPriority, { { "auto"_s, IntlRoundingPriority::Auto }, { "morePrecision"_s, IntlRoundingPriority::MorePrecision }, { "lessPrecision"_s, IntlRoundingPriority::LessPrecision } }, "roundingPriority must be either \"auto\", \"morePrecision\", or \"lessPrecision\""_s, IntlRoundingPriority::Auto); - RETURN_IF_EXCEPTION(scope, void()); - - bool hasSd = !minimumSignificantDigitsValue.isUndefined() || !maximumSignificantDigitsValue.isUndefined(); - bool hasFd = !minimumFractionDigitsValue.isUndefined() || !maximumFractionDigitsValue.isUndefined(); - bool needSd = hasSd || roundingPriority != IntlRoundingPriority::Auto; - bool needFd = (!hasSd && notation != IntlNotation::Compact) || roundingPriority != IntlRoundingPriority::Auto; - - if (needSd) { - if (hasSd) { - unsigned minimumSignificantDigits = intlDefaultNumberOption(globalObject, minimumSignificantDigitsValue, vm.propertyNames->minimumSignificantDigits, 1, 21, 1); - RETURN_IF_EXCEPTION(scope, void()); - unsigned maximumSignificantDigits = intlDefaultNumberOption(globalObject, maximumSignificantDigitsValue, vm.propertyNames->maximumSignificantDigits, minimumSignificantDigits, 21, 21); - RETURN_IF_EXCEPTION(scope, void()); - intlInstance->m_minimumSignificantDigits = minimumSignificantDigits; - intlInstance->m_maximumSignificantDigits = maximumSignificantDigits; - } else { - intlInstance->m_minimumSignificantDigits = 1; - intlInstance->m_maximumSignificantDigits = 21; - } - } - - if (needFd) { - if (hasFd) { - constexpr unsigned undefinedValue = UINT32_MAX; - unsigned minimumFractionDigits = intlDefaultNumberOption(globalObject, minimumFractionDigitsValue, vm.propertyNames->minimumFractionDigits, 0, 20, undefinedValue); - RETURN_IF_EXCEPTION(scope, void()); - unsigned maximumFractionDigits = intlDefaultNumberOption(globalObject, maximumFractionDigitsValue, vm.propertyNames->maximumFractionDigits, 0, 20, undefinedValue); - RETURN_IF_EXCEPTION(scope, void()); - - if (minimumFractionDigits == undefinedValue) - minimumFractionDigits = std::min(minimumFractionDigitsDefault, maximumFractionDigits); - else if (maximumFractionDigits == undefinedValue) - maximumFractionDigits = std::max(maximumFractionDigitsDefault, minimumFractionDigits); - else if (minimumFractionDigits > maximumFractionDigits) { - throwRangeError(globalObject, scope, "Computed minimumFractionDigits is larger than maximumFractionDigits"_s); - return; - } - - intlInstance->m_minimumFractionDigits = minimumFractionDigits; - intlInstance->m_maximumFractionDigits = maximumFractionDigits; - } else { - intlInstance->m_minimumFractionDigits = minimumFractionDigitsDefault; - intlInstance->m_maximumFractionDigits = maximumFractionDigitsDefault; - } - } - - if (needSd || needFd) { - if (roundingPriority == IntlRoundingPriority::MorePrecision) - intlInstance->m_roundingType = IntlRoundingType::MorePrecision; - else if (roundingPriority == IntlRoundingPriority::LessPrecision) - intlInstance->m_roundingType = IntlRoundingType::LessPrecision; - else if (hasSd) - intlInstance->m_roundingType = IntlRoundingType::SignificantDigits; - else - intlInstance->m_roundingType = IntlRoundingType::FractionDigits; - } else { - intlInstance->m_roundingType = IntlRoundingType::MorePrecision; - intlInstance->m_minimumFractionDigits = 0; - intlInstance->m_maximumFractionDigits = 0; - intlInstance->m_minimumSignificantDigits = 1; - intlInstance->m_maximumSignificantDigits = 2; - } -} - -template<typename IntlType> -void appendNumberFormatDigitOptionsToSkeleton(IntlType* intlInstance, StringBuilder& skeletonBuilder) -{ - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#integer-width - skeletonBuilder.append(" integer-width/", WTF::ICU::majorVersion() >= 67 ? '*' : '+'); // Prior to ICU 67, use the symbol + instead of *. - for (unsigned i = 0; i < intlInstance->m_minimumIntegerDigits; ++i) - skeletonBuilder.append('0'); - - if (intlInstance->m_roundingIncrement != 1) { - skeletonBuilder.append(" precision-increment/"); - auto string = numberToStringUnsigned<Vector<LChar, 10>>(intlInstance->m_roundingIncrement); - if (intlInstance->m_maximumFractionDigits >= string.size()) { - skeletonBuilder.append("0."); - for (unsigned i = 0; i < (intlInstance->m_maximumFractionDigits - string.size()); ++i) - skeletonBuilder.append('0'); - skeletonBuilder.appendCharacters(string.data(), string.size()); - } else { - unsigned nonFraction = string.size() - intlInstance->m_maximumFractionDigits; - skeletonBuilder.appendCharacters(string.data(), nonFraction); - skeletonBuilder.append('.'); - skeletonBuilder.appendCharacters(string.data() + nonFraction, intlInstance->m_maximumFractionDigits); - } - } else { - switch (intlInstance->m_roundingType) { - case IntlRoundingType::FractionDigits: { - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#fraction-precision - skeletonBuilder.append(" ."); - for (unsigned i = 0; i < intlInstance->m_minimumFractionDigits; ++i) - skeletonBuilder.append('0'); - for (unsigned i = 0; i < intlInstance->m_maximumFractionDigits - intlInstance->m_minimumFractionDigits; ++i) - skeletonBuilder.append('#'); - break; - } - case IntlRoundingType::SignificantDigits: { - // https://github.com/unicode-org/icu/blob/master/docs/userguide/format_parse/numbers/skeletons.md#significant-digits-precision - skeletonBuilder.append(' '); - for (unsigned i = 0; i < intlInstance->m_minimumSignificantDigits; ++i) - skeletonBuilder.append('@'); - for (unsigned i = 0; i < intlInstance->m_maximumSignificantDigits - intlInstance->m_minimumSignificantDigits; ++i) - skeletonBuilder.append('#'); - break; - } - case IntlRoundingType::MorePrecision: - case IntlRoundingType::LessPrecision: - // Before Intl.NumberFormat v3, it was CompactRounding mode, where we do not configure anything. - // So, if linked ICU is ~68, we do nothing. - if (WTF::ICU::majorVersion() >= 69) { - // https://github.com/unicode-org/icu/commit/d7db6c1f8655bb53153695b09a50029fd04a8364 - // https://github.com/unicode-org/icu/blob/main/docs/userguide/format_parse/numbers/skeletons.md#precision - skeletonBuilder.append(" ."); - for (unsigned i = 0; i < intlInstance->m_minimumFractionDigits; ++i) - skeletonBuilder.append('0'); - for (unsigned i = 0; i < intlInstance->m_maximumFractionDigits - intlInstance->m_minimumFractionDigits; ++i) - skeletonBuilder.append('#'); - skeletonBuilder.append('/'); - for (unsigned i = 0; i < intlInstance->m_minimumSignificantDigits; ++i) - skeletonBuilder.append('@'); - for (unsigned i = 0; i < intlInstance->m_maximumSignificantDigits - intlInstance->m_minimumSignificantDigits; ++i) - skeletonBuilder.append('#'); - skeletonBuilder.append(intlInstance->m_roundingType == IntlRoundingType::MorePrecision ? 'r' : 's'); - } - break; - } - } -} - -class IntlFieldIterator { -public: - WTF_MAKE_NONCOPYABLE(IntlFieldIterator); - - explicit IntlFieldIterator(UFieldPositionIterator& iterator) - : m_iterator(iterator) - { - } - - int32_t next(int32_t& beginIndex, int32_t& endIndex, UErrorCode&) - { - return ufieldpositer_next(&m_iterator, &beginIndex, &endIndex); - } - -private: - UFieldPositionIterator& m_iterator; -}; - // https://tc39.es/ecma402/#sec-unwrapnumberformat inline IntlNumberFormat* IntlNumberFormat::unwrapForOldFunctions(JSGlobalObject* globalObject, JSValue thisValue) { return unwrapForLegacyIntlConstructor<IntlNumberFormat>(globalObject, thisValue, globalObject->numberFormatConstructor()); } -// https://tc39.es/proposal-intl-numberformat-v3/out/numberformat/diff.html#sec-tointlmathematicalvalue -inline IntlMathematicalValue toIntlMathematicalValue(JSGlobalObject* globalObject, JSValue value) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (auto number = JSBigInt::tryExtractDouble(value)) - return IntlMathematicalValue { number.value() }; - - JSValue primitive = value.toPrimitive(globalObject, PreferredPrimitiveType::PreferNumber); - RETURN_IF_EXCEPTION(scope, { }); - - auto bigIntToIntlMathematicalValue = [](JSGlobalObject* globalObject, JSValue value) -> IntlMathematicalValue { - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (auto number = JSBigInt::tryExtractDouble(value)) - return IntlMathematicalValue { number.value() }; - - auto* bigInt = value.asHeapBigInt(); - auto string = bigInt->toString(globalObject, 10); - RETURN_IF_EXCEPTION(scope, { }); - return IntlMathematicalValue { - IntlMathematicalValue::NumberType::Integer, - bigInt->sign(), - string.ascii(), - }; - }; - - if (primitive.isBigInt()) - RELEASE_AND_RETURN(scope, bigIntToIntlMathematicalValue(globalObject, primitive)); - - if (!primitive.isString()) - RELEASE_AND_RETURN(scope, IntlMathematicalValue { primitive.toNumber(globalObject) }); - - String string = asString(primitive)->value(globalObject); - RETURN_IF_EXCEPTION(scope, { }); - - JSValue bigInt = JSBigInt::stringToBigInt(globalObject, string); - if (bigInt) { - // If it is -0, we cannot handle it in JSBigInt. Reparse the string as double. -#if USE(BIGINT32) - if (bigInt.isBigInt32() && !value.bigInt32AsInt32()) - return IntlMathematicalValue { jsToNumber(string) }; -#endif - if (bigInt.isHeapBigInt() && !asHeapBigInt(bigInt)->length()) - return IntlMathematicalValue { jsToNumber(string) }; - RELEASE_AND_RETURN(scope, bigIntToIntlMathematicalValue(globalObject, bigInt)); - } - - return IntlMathematicalValue { jsToNumber(string) }; -} - } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp 2022-03-28 15:11:04.214708945 -0500 @@ -28,25 +28,15 @@ #include "IntlNumberFormatPrototype.h" #include "BuiltinNames.h" -#include "IntlNumberFormatInlines.h" #include "JSBoundFunction.h" #include "JSCInlines.h" namespace JSC { static JSC_DECLARE_CUSTOM_GETTER(intlNumberFormatPrototypeGetterFormat); -static JSC_DECLARE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatToParts); static JSC_DECLARE_HOST_FUNCTION(intlNumberFormatPrototypeFuncResolvedOptions); static JSC_DECLARE_HOST_FUNCTION(intlNumberFormatFuncFormat); -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -static JSC_DECLARE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatRange); -#endif - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) -static JSC_DECLARE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatRangeToParts); -#endif - } #include "IntlNumberFormatPrototype.lut.h" @@ -58,15 +48,14 @@ const ClassInfo IntlNumberFormatPrototyp /* Source for IntlNumberFormatPrototype.lut.h @begin numberFormatPrototypeTable format intlNumberFormatPrototypeGetterFormat DontEnum|ReadOnly|CustomAccessor - formatToParts intlNumberFormatPrototypeFuncFormatToParts DontEnum|Function 1 resolvedOptions intlNumberFormatPrototypeFuncResolvedOptions DontEnum|Function 0 @end */ -IntlNumberFormatPrototype* IntlNumberFormatPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure) +IntlNumberFormatPrototype* IntlNumberFormatPrototype::create(VM& vm, JSGlobalObject*, Structure* structure) { IntlNumberFormatPrototype* object = new (NotNull, allocateCell<IntlNumberFormatPrototype>(vm)) IntlNumberFormatPrototype(vm, structure); - object->finishCreation(vm, globalObject); + object->finishCreation(vm); return object; } @@ -80,18 +69,11 @@ IntlNumberFormatPrototype::IntlNumberFor { } -void IntlNumberFormatPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) +void IntlNumberFormatPrototype::finishCreation(VM& vm) { Base::finishCreation(vm); ASSERT(inherits(vm, info())); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); - UNUSED_PARAM(globalObject); -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("formatRange", intlNumberFormatPrototypeFuncFormatRange, static_cast<unsigned>(PropertyAttribute::DontEnum), 2); -#endif -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) - JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("formatRangeToParts", intlNumberFormatPrototypeFuncFormatRangeToParts, static_cast<unsigned>(PropertyAttribute::DontEnum), 2); -#endif } // https://tc39.es/ecma402/#sec-number-format-functions @@ -101,13 +83,26 @@ JSC_DEFINE_HOST_FUNCTION(intlNumberForma auto scope = DECLARE_THROW_SCOPE(vm); auto* numberFormat = jsCast<IntlNumberFormat*>(callFrame->thisValue()); - auto value = toIntlMathematicalValue(globalObject, callFrame->argument(0)); - RETURN_IF_EXCEPTION(scope, { }); + JSValue bigIntOrNumber = callFrame->argument(0).toNumeric(globalObject); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); - if (auto number = value.tryGetDouble()) - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, number.value()))); + scope.release(); + if (bigIntOrNumber.isNumber()) { + double value = bigIntOrNumber.asNumber(); + return JSValue::encode(numberFormat->format(globalObject, value)); + } + +#if USE(BIGINT32) + if (bigIntOrNumber.isBigInt32()) { + JSBigInt* value = JSBigInt::createFrom(globalObject, bigIntOrNumber.bigInt32AsInt32()); + RETURN_IF_EXCEPTION(scope, { }); + RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, value))); + } +#endif - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->format(globalObject, WTFMove(value)))); + ASSERT(bigIntOrNumber.isHeapBigInt()); + JSBigInt* value = bigIntOrNumber.asHeapBigInt(); + return JSValue::encode(numberFormat->format(globalObject, value)); } JSC_DEFINE_CUSTOM_GETTER(intlNumberFormatPrototypeGetterFormat, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName)) @@ -139,38 +134,7 @@ JSC_DEFINE_CUSTOM_GETTER(intlNumberForma return JSValue::encode(boundFormat); } -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -JSC_DEFINE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatRange, (JSGlobalObject* globalObject, CallFrame* callFrame)) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - // Do not use unwrapForOldFunctions. - auto* numberFormat = jsDynamicCast<IntlNumberFormat*>(vm, callFrame->thisValue()); - if (UNLIKELY(!numberFormat)) - return JSValue::encode(throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatRange called on value that's not a NumberFormat"_s)); - - JSValue startValue = callFrame->argument(0); - JSValue endValue = callFrame->argument(1); - - if (startValue.isUndefined() || endValue.isUndefined()) - return throwVMTypeError(globalObject, scope, "start or end is undefined"_s); - - auto start = toIntlMathematicalValue(globalObject, startValue); - RETURN_IF_EXCEPTION(scope, { }); - - auto end = toIntlMathematicalValue(globalObject, endValue); - RETURN_IF_EXCEPTION(scope, { }); - - if (auto startNumber = start.tryGetDouble()) { - if (auto endNumber = end.tryGetDouble()) - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatRange(globalObject, startNumber.value(), endNumber.value()))); - } - - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatRange(globalObject, WTFMove(start), WTFMove(end)))); -} -#endif - +#if 0 JSC_DEFINE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatToParts, (JSGlobalObject* globalObject, CallFrame* callFrame)) { VM& vm = globalObject->vm(); @@ -184,51 +148,10 @@ JSC_DEFINE_HOST_FUNCTION(intlNumberForma if (UNLIKELY(!numberFormat)) return JSValue::encode(throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not a NumberFormat"_s)); -#if HAVE(ICU_U_NUMBER_FORMATTER) - auto value = toIntlMathematicalValue(globalObject, callFrame->argument(0)); - RETURN_IF_EXCEPTION(scope, { }); - - if (auto number = value.tryGetDouble()) - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatToParts(globalObject, number.value()))); - - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatToParts(globalObject, WTFMove(value)))); -#else double value = callFrame->argument(0).toNumber(globalObject); - RETURN_IF_EXCEPTION(scope, { }); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatToParts(globalObject, value))); -#endif -} - -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER_FORMAT_RANGE_TO_PARTS) -JSC_DEFINE_HOST_FUNCTION(intlNumberFormatPrototypeFuncFormatRangeToParts, (JSGlobalObject* globalObject, CallFrame* callFrame)) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - // Do not use unwrapForOldFunctions. - auto* numberFormat = jsDynamicCast<IntlNumberFormat*>(vm, callFrame->thisValue()); - if (UNLIKELY(!numberFormat)) - return JSValue::encode(throwTypeError(globalObject, scope, "Intl.NumberFormat.prototype.formatRangeToParts called on value that's not a NumberFormat"_s)); - - JSValue startValue = callFrame->argument(0); - JSValue endValue = callFrame->argument(1); - - if (startValue.isUndefined() || endValue.isUndefined()) - return throwVMTypeError(globalObject, scope, "start or end is undefined"_s); - - auto start = toIntlMathematicalValue(globalObject, startValue); - RETURN_IF_EXCEPTION(scope, { }); - - auto end = toIntlMathematicalValue(globalObject, endValue); - RETURN_IF_EXCEPTION(scope, { }); - - if (auto startNumber = start.tryGetDouble()) { - if (auto endNumber = end.tryGetDouble()) - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatRangeToParts(globalObject, startNumber.value(), endNumber.value()))); - } - - RELEASE_AND_RETURN(scope, JSValue::encode(numberFormat->formatRangeToParts(globalObject, WTFMove(start), WTFMove(end)))); } #endif diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.h 2022-03-28 15:11:04.218708967 -0500 @@ -49,7 +49,7 @@ public: private: IntlNumberFormatPrototype(VM&, Structure*); - void finishCreation(VM&, JSGlobalObject*); + void finishCreation(VM&); }; } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObject.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObject.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObject.cpp 2022-03-29 15:02:28.892121597 -0500 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObject.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -39,19 +39,11 @@ #include "IntlDisplayNames.h" #include "IntlDisplayNamesConstructor.h" #include "IntlDisplayNamesPrototype.h" -#include "IntlListFormat.h" -#include "IntlListFormatConstructor.h" -#include "IntlListFormatPrototype.h" -#include "IntlLocale.h" -#include "IntlLocaleConstructor.h" -#include "IntlLocalePrototype.h" #include "IntlNumberFormatConstructor.h" #include "IntlNumberFormatPrototype.h" #include "IntlObjectInlines.h" #include "IntlPluralRulesConstructor.h" #include "IntlPluralRulesPrototype.h" -#include "IntlRelativeTimeFormatConstructor.h" -#include "IntlRelativeTimeFormatPrototype.h" #include "IntlSegmenter.h" #include "IntlSegmenterConstructor.h" #include "IntlSegmenterPrototype.h" @@ -61,7 +53,6 @@ #include <unicode/ucal.h> #include <unicode/ucol.h> #include <unicode/ucurr.h> -#include <unicode/ufieldpositer.h> #include <unicode/uloc.h> #include <unicode/unumsys.h> #include <wtf/Assertions.h> @@ -100,20 +91,6 @@ static JSValue createDisplayNamesConstru return IntlDisplayNamesConstructor::create(vm, IntlDisplayNamesConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlDisplayNamesPrototype*>(globalObject->displayNamesStructure()->storedPrototypeObject())); } -static JSValue createListFormatConstructor(VM& vm, JSObject* object) -{ - IntlObject* intlObject = jsCast<IntlObject*>(object); - JSGlobalObject* globalObject = intlObject->globalObject(vm); - return IntlListFormatConstructor::create(vm, IntlListFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlListFormatPrototype*>(globalObject->listFormatStructure()->storedPrototypeObject())); -} - -static JSValue createLocaleConstructor(VM& vm, JSObject* object) -{ - IntlObject* intlObject = jsCast<IntlObject*>(object); - JSGlobalObject* globalObject = intlObject->globalObject(vm); - return IntlLocaleConstructor::create(vm, IntlLocaleConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlLocalePrototype*>(globalObject->localeStructure()->storedPrototypeObject())); -} - static JSValue createNumberFormatConstructor(VM& vm, JSObject* object) { IntlObject* intlObject = jsCast<IntlObject*>(object); @@ -128,13 +105,6 @@ static JSValue createPluralRulesConstruc return IntlPluralRulesConstructor::create(vm, IntlPluralRulesConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlPluralRulesPrototype*>(globalObject->pluralRulesStructure()->storedPrototypeObject())); } -static JSValue createRelativeTimeFormatConstructor(VM& vm, JSObject* object) -{ - IntlObject* intlObject = jsCast<IntlObject*>(object); - JSGlobalObject* globalObject = intlObject->globalObject(vm); - return IntlRelativeTimeFormatConstructor::create(vm, IntlRelativeTimeFormatConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()), jsCast<IntlRelativeTimeFormatPrototype*>(globalObject->relativeTimeFormatStructure()->storedPrototypeObject())); -} - static JSValue createSegmenterConstructor(VM& vm, JSObject* object) { IntlObject* intlObject = jsCast<IntlObject*>(object); @@ -154,10 +124,8 @@ namespace JSC { Collator createCollatorConstructor DontEnum|PropertyCallback DateTimeFormat createDateTimeFormatConstructor DontEnum|PropertyCallback DisplayNames createDisplayNamesConstructor DontEnum|PropertyCallback - Locale createLocaleConstructor DontEnum|PropertyCallback NumberFormat createNumberFormatConstructor DontEnum|PropertyCallback PluralRules createPluralRulesConstructor DontEnum|PropertyCallback - RelativeTimeFormat createRelativeTimeFormatConstructor DontEnum|PropertyCallback Segmenter createSegmenterConstructor DontEnum|PropertyCallback @end */ @@ -170,11 +138,13 @@ struct MatcherResult { const ClassInfo IntlObject::s_info = { "Intl", &Base::s_info, &intlObjectTable, nullptr, CREATE_METHOD_TABLE(IntlObject) }; +#if 0 void UFieldPositionIteratorDeleter::operator()(UFieldPositionIterator* iterator) const { if (iterator) ufieldpositer_close(iterator); } +#endif const MeasureUnit simpleUnits[43] = { { "area"_s, "acre"_s }, @@ -239,11 +209,6 @@ void IntlObject::finishCreation(VM& vm, Base::finishCreation(vm); ASSERT(inherits(vm, info())); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); -#if HAVE(ICU_U_LIST_FORMATTER) - putDirectWithoutTransition(vm, vm.propertyNames->ListFormat, createListFormatConstructor(vm, this), static_cast<unsigned>(PropertyAttribute::DontEnum)); -#else - UNUSED_PARAM(&createListFormatConstructor); -#endif if (Options::useIntlEnumeration()) JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("supportedValuesOf", intlObjectFuncSupportedValuesOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); } @@ -702,7 +667,7 @@ Vector<String> canonicalizeLocaleList(JS return seen; JSObject* localesObject; - if (locales.isString() || locales.inherits<IntlLocale>(vm)) { + if (locales.isString()) { JSArray* localesArray = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)); if (!localesArray) { throwOutOfMemoryError(globalObject, scope); @@ -739,15 +704,12 @@ Vector<String> canonicalizeLocaleList(JS } String tag; - if (kValue.inherits<IntlLocale>(vm)) - tag = jsCast<IntlLocale*>(kValue)->toString(); - else { - JSString* string = kValue.toString(globalObject); - RETURN_IF_EXCEPTION(scope, Vector<String>()); + JSString* string = kValue.toString(globalObject); + RETURN_IF_EXCEPTION(scope, Vector<String>()); - tag = string->value(globalObject); - RETURN_IF_EXCEPTION(scope, Vector<String>()); - } + tag = string->value(globalObject); + RETURN_IF_EXCEPTION(scope, Vector<String>()); + if (isStructurallyValidLanguageTag(tag)) { ASSERT(tag.isAllASCII()); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObject.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObject.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObject.h 2022-03-29 15:02:28.892121597 -0500 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObject.h 2022-03-28 15:11:04.218708967 -0500 @@ -99,7 +99,6 @@ inline const LocaleSet& intlDisplayNames inline const LocaleSet& intlNumberFormatAvailableLocales() { return intlAvailableLocales(); } inline const LocaleSet& intlPluralRulesAvailableLocales() { return intlAvailableLocales(); } inline const LocaleSet& intlRelativeTimeFormatAvailableLocales() { return intlAvailableLocales(); } -inline const LocaleSet& intlListFormatAvailableLocales() { return intlAvailableLocales(); } using CalendarID = unsigned; const Vector<String>& intlAvailableCalendars(); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObjectInlines.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObjectInlines.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlObjectInlines.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlObjectInlines.h 2022-03-28 15:11:04.218708967 -0500 @@ -151,45 +151,6 @@ ResultType intlOption(JSGlobalObject* gl return fallback; } -template<typename ResultType> -ResultType intlStringOrBooleanOption(JSGlobalObject* globalObject, JSObject* options, PropertyName property, ResultType trueValue, ResultType falsyValue, std::initializer_list<std::pair<ASCIILiteral, ResultType>> values, ASCIILiteral notFoundMessage, ResultType fallback) -{ - // https://tc39.es/proposal-intl-numberformat-v3/out/negotiation/diff.html#sec-getstringorbooleanoption - - ASSERT(values.size() > 0); - - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (!options) - return fallback; - - JSValue value = options->get(globalObject, property); - RETURN_IF_EXCEPTION(scope, { }); - - if (!value.isUndefined()) { - if (value.isBoolean() && value.asBoolean()) - return trueValue; - - bool valueBoolean = value.toBoolean(globalObject); - RETURN_IF_EXCEPTION(scope, { }); - - if (!valueBoolean) - return falsyValue; - - String stringValue = value.toWTFString(globalObject); - RETURN_IF_EXCEPTION(scope, { }); - - for (const auto& entry : values) { - if (entry.first == stringValue) - return entry.second; - } - throwException(globalObject, scope, createRangeError(globalObject, notFoundMessage)); - return { }; - } - - return fallback; -} ALWAYS_INLINE bool canUseASCIIUCADUCETComparison(UChar character) { diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRules.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRules.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRules.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRules.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -32,29 +32,29 @@ #include "JSCInlines.h" #include "ObjectConstructor.h" -#ifdef U_HIDE_DRAFT_API -#undef U_HIDE_DRAFT_API -#endif -#include <unicode/upluralrules.h> -#if HAVE(ICU_U_NUMBER_FORMATTER) -#include <unicode/unumberformatter.h> -#endif -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -#include <unicode/unumberrangeformatter.h> -#endif -#define U_HIDE_DRAFT_API 1 - namespace JSC { -void UPluralRulesDeleter::operator()(UPluralRules* pluralRules) +const ClassInfo IntlPluralRules::s_info = { "Object", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(IntlPluralRules) }; + +void IntlPluralRules::UPluralRulesDeleter::operator()(UPluralRules* pluralRules) const { if (pluralRules) uplrules_close(pluralRules); } -const ClassInfo IntlPluralRules::s_info = { "Object", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(IntlPluralRules) }; +void IntlPluralRules::UNumberFormatDeleter::operator()(UNumberFormat* numberFormat) const +{ + if (numberFormat) + unum_close(numberFormat); +} -using UEnumerationDeleter = ICUDeleter<uenum_close>; +struct UEnumerationDeleter { + void operator()(UEnumeration* enumeration) const + { + if (enumeration) + uenum_close(enumeration); + } +}; IntlPluralRules* IntlPluralRules::create(VM& vm, Structure* structure) { @@ -122,60 +122,54 @@ void IntlPluralRules::initializePluralRu m_type = intlOption<Type>(globalObject, options, vm.propertyNames->type, { { "cardinal"_s, Type::Cardinal }, { "ordinal"_s, Type::Ordinal } }, "type must be \"cardinal\" or \"ordinal\""_s, Type::Cardinal); RETURN_IF_EXCEPTION(scope, void()); - setNumberFormatDigitOptions(globalObject, this, options, 0, 3, IntlNotation::Standard); + unsigned minimumIntegerDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumIntegerDigits"), 1, 21, 1); RETURN_IF_EXCEPTION(scope, void()); + m_minimumIntegerDigits = minimumIntegerDigits; - auto locale = m_locale.utf8(); - UErrorCode status = U_ZERO_ERROR; + unsigned minimumFractionDigitsDefault = 0; + unsigned minimumFractionDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumFractionDigits"), 0, 20, minimumFractionDigitsDefault); + RETURN_IF_EXCEPTION(scope, void()); + m_minimumFractionDigits = minimumFractionDigits; -#if HAVE(ICU_U_NUMBER_FORMATTER) - StringBuilder skeletonBuilder; - skeletonBuilder.append("rounding-mode-half-up"); + unsigned maximumFractionDigitsDefault = std::max(minimumFractionDigits, 3u); + unsigned maximumFractionDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "maximumFractionDigits"), minimumFractionDigits, 20, maximumFractionDigitsDefault); + RETURN_IF_EXCEPTION(scope, void()); + m_maximumFractionDigits = maximumFractionDigits; - appendNumberFormatDigitOptionsToSkeleton(this, skeletonBuilder); + JSValue minimumSignificantDigitsValue = options->get(globalObject, Identifier::fromString(vm, "minimumSignificantDigits")); + RETURN_IF_EXCEPTION(scope, void()); - String skeleton = skeletonBuilder.toString(); - StringView skeletonView(skeleton); - auto upconverted = skeletonView.upconvertedCharacters(); + JSValue maximumSignificantDigitsValue = options->get(globalObject, Identifier::fromString(vm, "maximumSignificantDigits")); + RETURN_IF_EXCEPTION(scope, void()); - m_numberFormatter = std::unique_ptr<UNumberFormatter, UNumberFormatterDeleter>(unumf_openForSkeletonAndLocale(upconverted.get(), skeletonView.length(), locale.data(), &status)); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "failed to initialize PluralRules"_s); - return; + if (!minimumSignificantDigitsValue.isUndefined() || !maximumSignificantDigitsValue.isUndefined()) { + unsigned minimumSignificantDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "minimumSignificantDigits"), 1, 21, 1); + RETURN_IF_EXCEPTION(scope, void()); + unsigned maximumSignificantDigits = intlNumberOption(globalObject, options, Identifier::fromString(vm, "maximumSignificantDigits"), minimumSignificantDigits, 21, 21); + RETURN_IF_EXCEPTION(scope, void()); + m_minimumSignificantDigits = minimumSignificantDigits; + m_maximumSignificantDigits = maximumSignificantDigits; } -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - m_numberRangeFormatter = std::unique_ptr<UNumberRangeFormatter, UNumberRangeFormatterDeleter>(unumrf_openForSkeletonWithCollapseAndIdentityFallback(upconverted.get(), skeletonView.length(), UNUM_RANGE_COLLAPSE_NONE, UNUM_IDENTITY_FALLBACK_RANGE, locale.data(), nullptr, &status)); - if (U_FAILURE(status)) { - throwTypeError(globalObject, scope, "failed to initialize PluralRules"_s); - return; - } -#endif -#else - m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(UNUM_DECIMAL, nullptr, 0, locale.data(), nullptr, &status)); + UErrorCode status = U_ZERO_ERROR; + m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(UNUM_DECIMAL, nullptr, 0, m_locale.utf8().data(), nullptr, &status)); if (U_FAILURE(status)) { throwTypeError(globalObject, scope, "failed to initialize PluralRules"_s); return; } - switch (m_roundingType) { - case IntlRoundingType::FractionDigits: - unum_setAttribute(m_numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits); - unum_setAttribute(m_numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits); - unum_setAttribute(m_numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits); - break; - case IntlRoundingType::SignificantDigits: + if (m_minimumSignificantDigits) { unum_setAttribute(m_numberFormat.get(), UNUM_SIGNIFICANT_DIGITS_USED, true); unum_setAttribute(m_numberFormat.get(), UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits); unum_setAttribute(m_numberFormat.get(), UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits); - break; - case IntlRoundingType::MorePrecision: - case IntlRoundingType::LessPrecision: - break; + } else { + unum_setAttribute(m_numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits); + unum_setAttribute(m_numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits); + unum_setAttribute(m_numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits); } -#endif - m_pluralRules = std::unique_ptr<UPluralRules, UPluralRulesDeleter>(uplrules_openForType(locale.data(), m_type == Type::Ordinal ? UPLURAL_TYPE_ORDINAL : UPLURAL_TYPE_CARDINAL, &status)); + status = U_ZERO_ERROR; + m_pluralRules = std::unique_ptr<UPluralRules, UPluralRulesDeleter>(uplrules_openForType(m_locale.utf8().data(), m_type == Type::Ordinal ? UPLURAL_TYPE_ORDINAL : UPLURAL_TYPE_CARDINAL, &status)); if (U_FAILURE(status)) { throwTypeError(globalObject, scope, "failed to initialize PluralRules"_s); return; @@ -194,24 +188,14 @@ JSObject* IntlPluralRules::resolvedOptio options->putDirect(vm, vm.propertyNames->locale, jsNontrivialString(vm, m_locale)); options->putDirect(vm, vm.propertyNames->type, jsNontrivialString(vm, m_type == Type::Ordinal ? "ordinal"_s : "cardinal"_s)); options->putDirect(vm, vm.propertyNames->minimumIntegerDigits, jsNumber(m_minimumIntegerDigits)); - switch (m_roundingType) { - case IntlRoundingType::FractionDigits: - options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); - options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); - break; - case IntlRoundingType::SignificantDigits: - options->putDirect(vm, vm.propertyNames->minimumSignificantDigits, jsNumber(m_minimumSignificantDigits)); - options->putDirect(vm, vm.propertyNames->maximumSignificantDigits, jsNumber(m_maximumSignificantDigits)); - break; - case IntlRoundingType::MorePrecision: - case IntlRoundingType::LessPrecision: - options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); - options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); + options->putDirect(vm, vm.propertyNames->minimumFractionDigits, jsNumber(m_minimumFractionDigits)); + options->putDirect(vm, vm.propertyNames->maximumFractionDigits, jsNumber(m_maximumFractionDigits)); + if (m_minimumSignificantDigits) { options->putDirect(vm, vm.propertyNames->minimumSignificantDigits, jsNumber(m_minimumSignificantDigits)); options->putDirect(vm, vm.propertyNames->maximumSignificantDigits, jsNumber(m_maximumSignificantDigits)); - break; } +#if 0 JSArray* categories = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0); if (UNLIKELY(!categories)) { throwOutOfMemoryError(globalObject, scope); @@ -231,9 +215,9 @@ JSObject* IntlPluralRules::resolvedOptio RETURN_IF_EXCEPTION(scope, { }); } options->putDirect(vm, Identifier::fromString(vm, "pluralCategories"), categories); - options->putDirect(vm, vm.propertyNames->roundingMode, jsNontrivialString(vm, IntlNumberFormat::roundingPriorityString(m_roundingType))); +#endif - return options; + RELEASE_AND_RETURN(scope, options); } // https://tc39.es/ecma402/#sec-resolveplural @@ -248,61 +232,28 @@ JSValue IntlPluralRules::select(JSGlobal return jsNontrivialString(vm, "other"_s); UErrorCode status = U_ZERO_ERROR; - -#if HAVE(ICU_U_NUMBER_FORMATTER) - auto formattedNumber = std::unique_ptr<UFormattedNumber, ICUDeleter<unumf_closeResult>>(unumf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to select plural value"_s); - unumf_formatDouble(m_numberFormatter.get(), value, formattedNumber.get(), &status); + Vector<UChar, 32> buffer(32); + auto length = unum_formatDouble(m_numberFormat.get(), value, buffer.data(), buffer.size(), nullptr, &status); + if (status == U_BUFFER_OVERFLOW_ERROR) { + buffer.grow(length); + status = U_ZERO_ERROR; + unum_formatDouble(m_numberFormat.get(), value, buffer.data(), length, nullptr, &status); + } if (U_FAILURE(status)) return throwTypeError(globalObject, scope, "failed to select plural value"_s); - Vector<UChar, 32> buffer; - status = callBufferProducingFunction(uplrules_selectFormatted, m_pluralRules.get(), formattedNumber.get(), buffer); + + double formatted = unum_parseDouble(m_numberFormat.get(), buffer.data(), length, nullptr, &status); if (U_FAILURE(status)) return throwTypeError(globalObject, scope, "failed to select plural value"_s); - return jsString(vm, String(WTFMove(buffer))); -#else + + // Can only be 'zero', 'one', 'two', 'few', 'many' or 'other' + status = U_ZERO_ERROR; Vector<UChar, 8> result(8); - auto length = uplrules_selectWithFormat(m_pluralRules.get(), value, m_numberFormat.get(), result.data(), result.size(), &status); + length = uplrules_select(m_pluralRules.get(), formatted, result.data(), result.size(), &status); if (U_FAILURE(status)) return throwTypeError(globalObject, scope, "failed to select plural value"_s); return jsString(vm, String(result.data(), length)); -#endif } -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -JSValue IntlPluralRules::selectRange(JSGlobalObject* globalObject, double start, double end) const -{ - ASSERT(m_numberRangeFormatter); - - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - if (std::isnan(start) || std::isnan(end)) - return throwRangeError(globalObject, scope, "Passed numbers are out of range"_s); - - if (end < start) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - if (isNegativeZero(end) && start >= 0) - return throwRangeError(globalObject, scope, "start is larger than end"_s); - - UErrorCode status = U_ZERO_ERROR; - auto range = std::unique_ptr<UFormattedNumberRange, ICUDeleter<unumrf_closeResult>>(unumrf_openResult(&status)); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to select range of plural value"_s); - - unumrf_formatDoubleRange(m_numberRangeFormatter.get(), start, end, range.get(), &status); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to select range of plural value"_s); - - Vector<UChar, 32> buffer; - status = callBufferProducingFunction(uplrules_selectForRange, m_pluralRules.get(), range.get(), buffer); - if (U_FAILURE(status)) - return throwTypeError(globalObject, scope, "failed to select plural value"_s); - return jsString(vm, String(WTFMove(buffer))); -} -#endif - } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRules.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRules.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRules.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRules.h 2022-03-28 15:11:04.218708967 -0500 @@ -26,18 +26,12 @@ #pragma once -#include "IntlNumberFormat.h" +#include "JSObject.h" #include <unicode/unum.h> -#include <wtf/unicode/icu/ICUHelpers.h> - -struct UPluralRules; +#include <unicode/upluralrules.h> namespace JSC { -struct UPluralRulesDeleter { - JS_EXPORT_PRIVATE void operator()(UPluralRules*); -}; - enum class RelevantExtensionKey : uint8_t; class IntlPluralRules final : public JSNonFinalObject { @@ -62,19 +56,10 @@ public: DECLARE_INFO; - template<typename IntlType> - friend void setNumberFormatDigitOptions(JSGlobalObject*, IntlType*, JSObject*, unsigned minimumFractionDigitsDefault, unsigned maximumFractionDigitsDefault, IntlNotation); - template<typename IntlType> - friend void appendNumberFormatDigitOptionsToSkeleton(IntlType*, StringBuilder&); - void initializePluralRules(JSGlobalObject*, JSValue locales, JSValue options); JSValue select(JSGlobalObject*, double value) const; JSObject* resolvedOptions(JSGlobalObject*) const; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - JSValue selectRange(JSGlobalObject*, double start, double end) const; -#endif - private: IntlPluralRules(VM&, Structure*); void finishCreation(VM&); @@ -84,16 +69,15 @@ private: enum class Type : bool { Cardinal, Ordinal }; + struct UPluralRulesDeleter { + void operator()(UPluralRules*) const; + }; + struct UNumberFormatDeleter { + void operator()(UNumberFormat*) const; + }; + std::unique_ptr<UPluralRules, UPluralRulesDeleter> m_pluralRules; -#if HAVE(ICU_U_NUMBER_FORMATTER) - std::unique_ptr<UNumberFormatter, UNumberFormatterDeleter> m_numberFormatter; -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - std::unique_ptr<UNumberRangeFormatter, UNumberRangeFormatterDeleter> m_numberRangeFormatter; -#endif -#else - using UNumberFormatDeleter = ICUDeleter<unum_close>; std::unique_ptr<UNumberFormat, UNumberFormatDeleter> m_numberFormat; -#endif String m_locale; unsigned m_minimumIntegerDigits { 1 }; @@ -101,8 +85,6 @@ private: unsigned m_maximumFractionDigits { 3 }; unsigned m_minimumSignificantDigits { 0 }; unsigned m_maximumSignificantDigits { 0 }; - unsigned m_roundingIncrement { 1 }; - IntlRoundingType m_roundingType { IntlRoundingType::FractionDigits }; Type m_type { Type::Cardinal }; }; diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -33,9 +33,6 @@ namespace JSC { static JSC_DECLARE_HOST_FUNCTION(intlPluralRulesPrototypeFuncSelect); -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -static JSC_DECLARE_HOST_FUNCTION(intlPluralRulesPrototypeFuncSelectRange); -#endif static JSC_DECLARE_HOST_FUNCTION(intlPluralRulesPrototypeFuncResolvedOptions); } @@ -53,10 +50,10 @@ const ClassInfo IntlPluralRulesPrototype @end */ -IntlPluralRulesPrototype* IntlPluralRulesPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure) +IntlPluralRulesPrototype* IntlPluralRulesPrototype::create(VM& vm, JSGlobalObject*, Structure* structure) { IntlPluralRulesPrototype* object = new (NotNull, allocateCell<IntlPluralRulesPrototype>(vm)) IntlPluralRulesPrototype(vm, structure); - object->finishCreation(vm, globalObject); + object->finishCreation(vm); return object; } @@ -70,15 +67,11 @@ IntlPluralRulesPrototype::IntlPluralRule { } -void IntlPluralRulesPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) +void IntlPluralRulesPrototype::finishCreation(VM& vm) { Base::finishCreation(vm); ASSERT(inherits(vm, info())); JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); - UNUSED_PARAM(globalObject); -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) - JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->selectRange, intlPluralRulesPrototypeFuncSelectRange, static_cast<unsigned>(PropertyAttribute::DontEnum), 2); -#endif } JSC_DEFINE_HOST_FUNCTION(intlPluralRulesPrototypeFuncSelect, (JSGlobalObject* globalObject, CallFrame* callFrame)) @@ -99,33 +92,6 @@ JSC_DEFINE_HOST_FUNCTION(intlPluralRules RELEASE_AND_RETURN(scope, JSValue::encode(pluralRules->select(globalObject, value))); } -#if HAVE(ICU_U_NUMBER_RANGE_FORMATTER) -JSC_DEFINE_HOST_FUNCTION(intlPluralRulesPrototypeFuncSelectRange, (JSGlobalObject* globalObject, CallFrame* callFrame)) -{ - VM& vm = globalObject->vm(); - auto scope = DECLARE_THROW_SCOPE(vm); - - // https://tc39.es/proposal-intl-numberformat-v3/out/pluralrules/diff.html#sec-intl.pluralrules.prototype.selectrange - IntlPluralRules* pluralRules = jsDynamicCast<IntlPluralRules*>(vm, callFrame->thisValue()); - if (!pluralRules) - return JSValue::encode(throwTypeError(globalObject, scope, "Intl.PluralRules.prototype.selectRange called on value that's not a PluralRules"_s)); - - JSValue startValue = callFrame->argument(0); - JSValue endValue = callFrame->argument(1); - - if (startValue.isUndefined() || endValue.isUndefined()) - return throwVMTypeError(globalObject, scope, "start or end is undefined"_s); - - double start = startValue.toNumber(globalObject); - RETURN_IF_EXCEPTION(scope, { }); - - double end = endValue.toNumber(globalObject); - RETURN_IF_EXCEPTION(scope, { }); - - RELEASE_AND_RETURN(scope, JSValue::encode(pluralRules->selectRange(globalObject, start, end))); -} -#endif - JSC_DEFINE_HOST_FUNCTION(intlPluralRulesPrototypeFuncResolvedOptions, (JSGlobalObject* globalObject, CallFrame* callFrame)) { VM& vm = globalObject->vm(); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlPluralRulesPrototype.h 2022-03-28 15:11:04.218708967 -0500 @@ -49,7 +49,7 @@ public: private: IntlPluralRulesPrototype(VM&, Structure*); - void finishCreation(VM&, JSGlobalObject*); + void finishCreation(VM&); }; } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -27,7 +27,7 @@ #include "config.h" #include "IntlRelativeTimeFormat.h" -#include "IntlNumberFormatInlines.h" +#include "IntlNumberFormat.h" #include "IntlObjectInlines.h" #include "JSCInlines.h" #include "ObjectConstructor.h" @@ -40,6 +40,18 @@ const ClassInfo IntlRelativeTimeFormat:: namespace IntlRelativeTimeFormatInternal { } +void IntlRelativeTimeFormat::URelativeDateTimeFormatterDeleter::operator()(URelativeDateTimeFormatter* relativeDateTimeFormatter) const +{ + if (relativeDateTimeFormatter) + ureldatefmt_close(relativeDateTimeFormatter); +} + +void IntlRelativeTimeFormat::UNumberFormatDeleter::operator()(UNumberFormat* numberFormat) const +{ + if (numberFormat) + unum_close(numberFormat); +} + IntlRelativeTimeFormat* IntlRelativeTimeFormat::create(VM& vm, Structure* structure) { auto* format = new (NotNull, allocateCell<IntlRelativeTimeFormat>(vm)) IntlRelativeTimeFormat(vm, structure); @@ -317,8 +329,7 @@ JSValue IntlRelativeTimeFormat::formatTo RETURN_IF_EXCEPTION(scope, { }); } - IntlFieldIterator fieldIterator(*iterator.get()); - IntlNumberFormat::formatToPartsInternal(globalObject, IntlNumberFormat::Style::Decimal, std::signbit(absValue), IntlMathematicalValue::numberTypeFromDouble(absValue), formattedNumber, fieldIterator, parts, nullptr, jsString(vm, singularUnit(unit).toString())); + IntlNumberFormat::formatToPartsInternal(globalObject, absValue, formattedNumber, iterator.get(), parts, jsString(vm, singularUnit(unit).toString())); RETURN_IF_EXCEPTION(scope, { }); } diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/IntlRelativeTimeFormat.h 2022-03-28 15:11:04.218708967 -0500 @@ -28,7 +28,6 @@ #include "JSObject.h" #include <unicode/ureldatefmt.h> -#include <wtf/unicode/icu/ICUHelpers.h> namespace JSC { @@ -72,8 +71,12 @@ private: enum class Style : uint8_t { Long, Short, Narrow }; - using URelativeDateTimeFormatterDeleter = ICUDeleter<ureldatefmt_close>; - using UNumberFormatDeleter = ICUDeleter<unum_close>; + struct URelativeDateTimeFormatterDeleter { + void operator()(URelativeDateTimeFormatter*) const; + }; + struct UNumberFormatDeleter { + void operator()(UNumberFormat*) const; + }; static ASCIILiteral styleString(Style); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSBigInt.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSBigInt.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSBigInt.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSBigInt.h 2022-03-28 15:11:04.218708967 -0500 @@ -464,8 +464,6 @@ public: return hashSlow(); } - static std::optional<double> tryExtractDouble(JSValue); - private: JSBigInt(VM&, Structure*, Digit*, unsigned length); @@ -678,42 +676,4 @@ ALWAYS_INLINE JSValue tryConvertToBigInt return bigInt; } -ALWAYS_INLINE std::optional<double> JSBigInt::tryExtractDouble(JSValue value) -{ - if (value.isNumber()) - return value.asNumber(); - - if (!value.isBigInt()) - return std::nullopt; - -#if USE(BIGINT32) - if (value.isBigInt32()) - return value.bigInt32AsInt32(); -#endif - - ASSERT(value.isHeapBigInt()); - JSBigInt* bigInt = value.asHeapBigInt(); - if (!bigInt->length()) - return 0; - - uint64_t integer = 0; - if constexpr (sizeof(Digit) == 8) { - if (bigInt->length() != 1) - return std::nullopt; - integer = bigInt->digit(0); - } else { - ASSERT(sizeof(Digit) == 4); - if (bigInt->length() > 2) - return std::nullopt; - integer = bigInt->digit(0); - if (bigInt->length() == 2) - integer |= (static_cast<uint64_t>(bigInt->digit(1)) << 32); - } - - if (integer <= static_cast<uint64_t>(maxSafeInteger())) - return (bigInt->sign()) ? -static_cast<double>(integer) : static_cast<double>(integer); - - return std::nullopt; -} - } // namespace JSC diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSDateMath.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSDateMath.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSDateMath.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSDateMath.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -386,7 +386,7 @@ void DateCache::timeZoneCacheSlow() m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(cache); #else // Do not use icu::TimeZone::createDefault. ICU internally has a cache for timezone and createDefault returns this cached value. - m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::detectHostTimeZone())); + m_timeZoneCache = std::unique_ptr<OpaqueICUTimeZone, OpaqueICUTimeZoneDeleter>(bitwise_cast<OpaqueICUTimeZone*>(icu::TimeZone::createDefault())); #endif } diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObject.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObject.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObject.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObject.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -80,18 +80,12 @@ #include "IntlDateTimeFormatPrototype.h" #include "IntlDisplayNames.h" #include "IntlDisplayNamesPrototype.h" -#include "IntlListFormat.h" -#include "IntlListFormatPrototype.h" -#include "IntlLocale.h" -#include "IntlLocalePrototype.h" #include "IntlNumberFormat.h" #include "IntlNumberFormatConstructor.h" #include "IntlNumberFormatPrototype.h" #include "IntlObject.h" #include "IntlPluralRules.h" #include "IntlPluralRulesPrototype.h" -#include "IntlRelativeTimeFormat.h" -#include "IntlRelativeTimeFormatPrototype.h" #include "IntlSegmentIterator.h" #include "IntlSegmentIteratorPrototype.h" #include "IntlSegmenter.h" @@ -1179,30 +1173,12 @@ capitalName ## Constructor* lowerName ## IntlDisplayNamesPrototype* displayNamesPrototype = IntlDisplayNamesPrototype::create(init.vm, IntlDisplayNamesPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); init.set(IntlDisplayNames::createStructure(init.vm, globalObject, displayNamesPrototype)); }); - m_listFormatStructure.initLater( - [] (const Initializer<Structure>& init) { - JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); - IntlListFormatPrototype* listFormatPrototype = IntlListFormatPrototype::create(init.vm, IntlListFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); - init.set(IntlListFormat::createStructure(init.vm, globalObject, listFormatPrototype)); - }); - m_localeStructure.initLater( - [] (const Initializer<Structure>& init) { - JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); - IntlLocalePrototype* localePrototype = IntlLocalePrototype::create(init.vm, IntlLocalePrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); - init.set(IntlLocale::createStructure(init.vm, globalObject, localePrototype)); - }); m_pluralRulesStructure.initLater( [] (const Initializer<Structure>& init) { JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); IntlPluralRulesPrototype* pluralRulesPrototype = IntlPluralRulesPrototype::create(init.vm, globalObject, IntlPluralRulesPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); init.set(IntlPluralRules::createStructure(init.vm, globalObject, pluralRulesPrototype)); }); - m_relativeTimeFormatStructure.initLater( - [] (const Initializer<Structure>& init) { - JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); - IntlRelativeTimeFormatPrototype* relativeTimeFormatPrototype = IntlRelativeTimeFormatPrototype::create(init.vm, IntlRelativeTimeFormatPrototype::createStructure(init.vm, globalObject, globalObject->objectPrototype())); - init.set(IntlRelativeTimeFormat::createStructure(init.vm, globalObject, relativeTimeFormatPrototype)); - }); m_segmentIteratorStructure.initLater( [] (const Initializer<Structure>& init) { JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(init.owner); @@ -2192,10 +2168,7 @@ void JSGlobalObject::visitChildrenImpl(J thisObject->m_defaultCollator.visit(visitor); thisObject->m_collatorStructure.visit(visitor); thisObject->m_displayNamesStructure.visit(visitor); - thisObject->m_listFormatStructure.visit(visitor); - thisObject->m_localeStructure.visit(visitor); thisObject->m_pluralRulesStructure.visit(visitor); - thisObject->m_relativeTimeFormatStructure.visit(visitor); thisObject->m_segmentIteratorStructure.visit(visitor); thisObject->m_segmenterStructure.visit(visitor); thisObject->m_segmentsStructure.visit(visitor); diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp 2022-03-28 15:11:04.218708967 -0500 @@ -169,7 +169,7 @@ static JSValue decode(JSGlobalObject* gl int charLen = 0; if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) { const char b0 = Lexer<CharType>::convertHex(p[1], p[2]); - const int sequenceLen = 1 + U8_COUNT_TRAIL_BYTES(b0); + const int sequenceLen = 1 + U8_COUNT_TRAIL_BYTES(static_cast<unsigned char>(b0)); if (k <= length - sequenceLen * 3) { charLen = sequenceLen * 3; uint8_t sequence[U8_MAX_LENGTH]; diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObject.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObject.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/JSGlobalObject.h 2022-02-23 02:58:53.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/JSGlobalObject.h 2022-03-28 15:11:04.218708967 -0500 @@ -325,10 +325,7 @@ public: LazyProperty<JSGlobalObject, IntlCollator> m_defaultCollator; LazyProperty<JSGlobalObject, Structure> m_collatorStructure; LazyProperty<JSGlobalObject, Structure> m_displayNamesStructure; - LazyProperty<JSGlobalObject, Structure> m_listFormatStructure; - LazyProperty<JSGlobalObject, Structure> m_localeStructure; LazyProperty<JSGlobalObject, Structure> m_pluralRulesStructure; - LazyProperty<JSGlobalObject, Structure> m_relativeTimeFormatStructure; LazyProperty<JSGlobalObject, Structure> m_segmentIteratorStructure; LazyProperty<JSGlobalObject, Structure> m_segmenterStructure; LazyProperty<JSGlobalObject, Structure> m_segmentsStructure; @@ -892,11 +889,8 @@ public: Structure* collatorStructure() { return m_collatorStructure.get(this); } Structure* dateTimeFormatStructure() { return m_dateTimeFormatStructure.get(this); } Structure* displayNamesStructure() { return m_displayNamesStructure.get(this); } - Structure* listFormatStructure() { return m_listFormatStructure.get(this); } Structure* numberFormatStructure() { return m_numberFormatStructure.get(this); } - Structure* localeStructure() { return m_localeStructure.get(this); } Structure* pluralRulesStructure() { return m_pluralRulesStructure.get(this); } - Structure* relativeTimeFormatStructure() { return m_relativeTimeFormatStructure.get(this); } Structure* segmentIteratorStructure() { return m_segmentIteratorStructure.get(this); } Structure* segmenterStructure() { return m_segmenterStructure.get(this); } Structure* segmentsStructure() { return m_segmentsStructure.get(this); } diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/MathCommon.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/MathCommon.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/MathCommon.h 2022-02-23 02:58:54.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/MathCommon.h 2022-03-28 15:11:04.218708967 -0500 @@ -63,11 +63,6 @@ inline bool isSafeInteger(double value) return std::trunc(value) == value && std::abs(value) <= maxSafeInteger(); } -inline bool isNegativeZero(double value) -{ - return std::signbit(value) && value == 0; -} - // This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec. // Note that this operation is identical to ToUInt32 other than to interpretation // of the resulting bit-pattern (as such this method is also called to implement diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/TemporalObject.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/TemporalObject.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/TemporalObject.cpp 2022-02-23 02:58:54.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/TemporalObject.cpp 2022-03-29 15:04:28.984761209 -0500 @@ -462,14 +462,6 @@ double roundNumberToIncrement(double x, return std::trunc(quotient) * increment; case RoundingMode::HalfExpand: return std::round(quotient) * increment; - - // They are not supported in Temporal right now. - case RoundingMode::Expand: - case RoundingMode::HalfCeil: - case RoundingMode::HalfFloor: - case RoundingMode::HalfTrunc: - case RoundingMode::HalfEven: - return std::trunc(quotient) * increment; } RELEASE_ASSERT_NOT_REACHED(); @@ -510,13 +502,6 @@ Int128 roundNumberToIncrement(Int128 x, if (abs(remainder * 2) >= increment) quotient += sign ? -1 : 1; break; - // They are not supported in Temporal right now. - case RoundingMode::Expand: - case RoundingMode::HalfCeil: - case RoundingMode::HalfFloor: - case RoundingMode::HalfTrunc: - case RoundingMode::HalfEven: - break; } return quotient * increment; } diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/TemporalObject.h webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/TemporalObject.h --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/runtime/TemporalObject.h 2022-02-23 02:58:54.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/runtime/TemporalObject.h 2022-03-28 15:11:04.222708988 -0500 @@ -88,13 +88,8 @@ private: enum class RoundingMode : uint8_t { Ceil, Floor, - Expand, Trunc, - HalfCeil, - HalfFloor, - HalfExpand, - HalfTrunc, - HalfEven + HalfExpand }; enum class Precision : uint8_t { diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/Sources.txt webkitgtk-2.36.0.icu52/Source/JavaScriptCore/Sources.txt --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/Sources.txt 2022-02-23 02:58:52.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/Sources.txt 2022-03-28 15:11:04.222708988 -0500 @@ -824,22 +824,13 @@ runtime/IntlDateTimeFormatPrototype.cpp runtime/IntlDisplayNames.cpp runtime/IntlDisplayNamesConstructor.cpp runtime/IntlDisplayNamesPrototype.cpp -runtime/IntlListFormat.cpp @no-unify // Confine U_HIDE_DRAFT_API's effect in this file. -runtime/IntlListFormatConstructor.cpp -runtime/IntlListFormatPrototype.cpp -runtime/IntlLocale.cpp -runtime/IntlLocaleConstructor.cpp -runtime/IntlLocalePrototype.cpp -runtime/IntlNumberFormat.cpp @no-unify // Confine U_HIDE_DRAFT_API's effect in this file. +runtime/IntlNumberFormat.cpp runtime/IntlNumberFormatConstructor.cpp runtime/IntlNumberFormatPrototype.cpp runtime/IntlObject.cpp -runtime/IntlPluralRules.cpp @no-unify // Confine U_HIDE_DRAFT_API's effect to this file. +runtime/IntlPluralRules.cpp runtime/IntlPluralRulesConstructor.cpp runtime/IntlPluralRulesPrototype.cpp -runtime/IntlRelativeTimeFormat.cpp -runtime/IntlRelativeTimeFormatConstructor.cpp -runtime/IntlRelativeTimeFormatPrototype.cpp runtime/IntlSegmentIterator.cpp runtime/IntlSegmentIteratorPrototype.cpp runtime/IntlSegmenter.cpp diff -urp webkitgtk-2.36.0.icu60/Source/JavaScriptCore/tools/JSDollarVM.cpp webkitgtk-2.36.0.icu52/Source/JavaScriptCore/tools/JSDollarVM.cpp --- webkitgtk-2.36.0.icu60/Source/JavaScriptCore/tools/JSDollarVM.cpp 2022-02-23 02:58:54.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/JavaScriptCore/tools/JSDollarVM.cpp 2022-03-28 15:11:04.222708988 -0500 @@ -61,7 +61,6 @@ #include <wtf/Language.h> #include <wtf/ProcessID.h> #include <wtf/StringPrintStream.h> -#include <wtf/unicode/icu/ICUHelpers.h> #if !USE(SYSTEM_MALLOC) #include <bmalloc/BPlatform.h> @@ -3664,7 +3663,9 @@ JSC_DEFINE_HOST_FUNCTION(functionSetUser JSC_DEFINE_HOST_FUNCTION(functionICUVersion, (JSGlobalObject*, CallFrame*)) { DollarVMAssertScope assertScope; - return JSValue::encode(jsNumber(WTF::ICU::majorVersion())); + UVersionInfo versionInfo; + u_getVersion(versionInfo); + return JSValue::encode(jsNumber(versionInfo[0])); } JSC_DEFINE_HOST_FUNCTION(functionICUHeaderVersion, (JSGlobalObject*, CallFrame*)) diff -urp webkitgtk-2.36.0.icu60/Source/WebCore/platform/text/CharacterProperties.h webkitgtk-2.36.0.icu52/Source/WebCore/platform/text/CharacterProperties.h --- webkitgtk-2.36.0.icu60/Source/WebCore/platform/text/CharacterProperties.h 2022-02-23 02:59:02.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/WebCore/platform/text/CharacterProperties.h 2022-03-28 15:11:04.222708988 -0500 @@ -41,10 +41,8 @@ static_assert(UBLOCK_SYMBOLS_AND_PICTOGR switch (static_cast<int>(ublock_getCode(character))) { case UBLOCK_MISCELLANEOUS_SYMBOLS: case UBLOCK_DINGBATS: - case UBLOCK_MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS: case UBLOCK_EMOTICONS: case UBLOCK_TRANSPORT_AND_MAP_SYMBOLS: - case UBLOCK_SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS: case UBLOCK_SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A: return true; default: @@ -80,12 +78,12 @@ inline bool isEmojiRegionalIndicator(UCh inline bool isEmojiWithPresentationByDefault(UChar32 character) { - return u_hasBinaryProperty(character, UCHAR_EMOJI_PRESENTATION); + return false; } inline bool isEmojiModifierBase(UChar32 character) { - return u_hasBinaryProperty(character, UCHAR_EMOJI_MODIFIER_BASE); + return false; } inline bool isDefaultIgnorableCodePoint(UChar32 character) diff -urp webkitgtk-2.36.0.icu60/Source/WTF/wtf/Range.h webkitgtk-2.36.0.icu52/Source/WTF/wtf/Range.h --- webkitgtk-2.36.0.icu60/Source/WTF/wtf/Range.h 2022-02-23 02:58:57.000000000 -0600 +++ webkitgtk-2.36.0.icu52/Source/WTF/wtf/Range.h 2022-03-28 15:11:04.222708988 -0500 @@ -105,8 +105,6 @@ public: Type begin() const { return m_begin; } Type end() const { return m_end; } - Type distance() const { return end() - begin(); } - bool overlaps(const Range& other) const { return WTF::rangesOverlap(m_begin, m_end, other.m_begin, other.m_end);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor