Title: [260145] trunk
Revision
260145
Author
ross.kirsl...@sony.com
Date
2020-04-15 12:51:24 -0700 (Wed, 15 Apr 2020)

Log Message

[ECMA-402] Fix Intl.DateTimeFormat patterns and fields in WebKit
https://bugs.webkit.org/show_bug.cgi?id=209783

Reviewed by Keith Miller.

JSTests:

* stress/date-toLocaleString.js:
* stress/intl-datetimeformat.js:
Add tests and fix some existing ones.

* test262/config.yaml:
* test262/expectations.yaml:
Mark eight test cases passing...but skip half of them due to outdated CLDR data in macOS system ICU.

Source/_javascript_Core:

This patch implements two intertwining normative changes to Intl.DateTimeFormat:
  - Calendar setting must be taken into account when choosing a date-time pattern
    https://github.com/tc39/ecma402/pull/349
  - formatToParts must recognize relatedYear and yearName parts
    https://github.com/tc39/ecma402/pull/349

* runtime/IntlDateTimeFormat.cpp:
(JSC::IntlDateTimeFormat::initializeDateTimeFormat):
(JSC::IntlDateTimeFormat::partTypeString):

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (260144 => 260145)


--- trunk/JSTests/ChangeLog	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/JSTests/ChangeLog	2020-04-15 19:51:24 UTC (rev 260145)
@@ -1,3 +1,18 @@
+2020-04-15  Ross Kirsling  <ross.kirsl...@sony.com>
+
+        [ECMA-402] Fix Intl.DateTimeFormat patterns and fields in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=209783
+
+        Reviewed by Keith Miller.
+
+        * stress/date-toLocaleString.js:
+        * stress/intl-datetimeformat.js:
+        Add tests and fix some existing ones.
+
+        * test262/config.yaml:
+        * test262/expectations.yaml:
+        Mark eight test cases passing...but skip half of them due to outdated CLDR data in macOS system ICU.
+
 2020-04-15  Devin Rousso  <drou...@apple.com>
 
         [ESNext] Implement logical assignment operators

Modified: trunk/JSTests/stress/date-toLocaleString.js (260144 => 260145)


--- trunk/JSTests/stress/date-toLocaleString.js	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/JSTests/stress/date-toLocaleString.js	2020-04-15 19:51:24 UTC (rev 260145)
@@ -45,6 +45,9 @@
 // Test that locale parameter is passed through properly.
 shouldThrow(() => new Date().toLocaleString('i'), RangeError);
 shouldBe(new Date(0).toLocaleString('zh-Hans-CN-u-nu-hanidec', { timeZone: 'UTC' }), '一九七〇/一/一 上午一二:〇〇:〇〇');
+shouldBe(new Date(0).toLocaleString('zh-Hans-CN', { timeZone: 'UTC', numberingSystem: 'hanidec' }), '一九七〇/一/一 上午一二:〇〇:〇〇');
+shouldBe(new Date(0).toLocaleString('en-u-ca-chinese', { year: 'numeric' }), '1969(ji-you)');
+shouldBe(new Date(0).toLocaleString('en', { year: 'numeric', calendar: 'chinese' }), '1969(ji-you)');
 
 // Defaults to mdy, hms
 shouldBe(new Date(0).toLocaleString('en', { timeZone: 'UTC' }), '1/1/1970, 12:00:00 AM');
@@ -81,6 +84,9 @@
 // Test that locale parameter is passed through properly.
 shouldThrow(() => new Date().toLocaleDateString('i'), RangeError);
 shouldBe(new Date(0).toLocaleDateString('zh-Hans-CN-u-nu-hanidec', { timeZone: 'UTC' }), '一九七〇/一/一');
+shouldBe(new Date(0).toLocaleDateString('zh-Hans-CN', { timeZone: 'UTC', numberingSystem: 'hanidec' }), '一九七〇/一/一');
+shouldBe(new Date(0).toLocaleDateString('en-u-ca-chinese', { year: 'numeric' }), '1969(ji-you)');
+shouldBe(new Date(0).toLocaleDateString('en', { year: 'numeric', calendar: 'chinese' }), '1969(ji-you)');
 
 // Defaults to mdy
 shouldBe(new Date(0).toLocaleDateString('en', { timeZone: 'UTC' }), '1/1/1970');
@@ -119,6 +125,9 @@
 // Test that locale parameter is passed through properly.
 shouldThrow(() => new Date().toLocaleTimeString('i'), RangeError);
 shouldBe(new Date(0).toLocaleTimeString('zh-Hans-CN-u-nu-hanidec', { timeZone: 'UTC' }), "上午一二:〇〇:〇〇");
+shouldBe(new Date(0).toLocaleTimeString('zh-Hans-CN', { timeZone: 'UTC', numberingSystem: 'hanidec' }), "上午一二:〇〇:〇〇");
+shouldBe(new Date(0).toLocaleTimeString('en-u-ca-chinese', { year: 'numeric' }), '1969(ji-you), 4:00:00 PM');
+shouldBe(new Date(0).toLocaleTimeString('en', { year: 'numeric', calendar: 'chinese' }), '1969(ji-you), 4:00:00 PM');
 
 // Defaults to hms
 shouldBe(new Date(0).toLocaleTimeString('en', { timeZone: 'UTC' }), "12:00:00 AM");

Modified: trunk/JSTests/stress/intl-datetimeformat.js (260144 => 260145)


--- trunk/JSTests/stress/intl-datetimeformat.js	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/JSTests/stress/intl-datetimeformat.js	2020-04-15 19:51:24 UTC (rev 260145)
@@ -306,26 +306,26 @@
 shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-rgsa').resolvedOptions().calendar, 'islamic-rgsa');
 
 // Calendar-sensitive format().
-shouldBe(Intl.DateTimeFormat('en-u-ca-buddhist', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/2558');
-shouldBe(Intl.DateTimeFormat('en-u-ca-chinese', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '11/15/32');
-shouldBe(Intl.DateTimeFormat('en-u-ca-coptic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/1732');
-shouldBe(Intl.DateTimeFormat('en-u-ca-dangi', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '11/15/32');
-shouldBe(Intl.DateTimeFormat('en-u-ca-ethioaa', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/7508');
-shouldBe(Intl.DateTimeFormat('en-u-ca-ethiopic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/2008');
+shouldBe(Intl.DateTimeFormat('en-u-ca-buddhist', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/2558 BE');
+shouldBe(Intl.DateTimeFormat('en-u-ca-chinese', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '11/15/2015');
+shouldBe(Intl.DateTimeFormat('en-u-ca-coptic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/1732 ERA1');
+shouldBe(Intl.DateTimeFormat('en-u-ca-dangi', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '11/15/2015');
+shouldBe(Intl.DateTimeFormat('en-u-ca-ethioaa', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/7508 ERA0');
+shouldBe(Intl.DateTimeFormat('en-u-ca-ethiopic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/2008 ERA1');
 shouldBe(Intl.DateTimeFormat('en-u-ca-gregory', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/2015');
-shouldBe(Intl.DateTimeFormat('en-u-ca-hebrew', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/13/5776');
-shouldBe(Intl.DateTimeFormat('en-u-ca-indian', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '10/4/1937');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamicc', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/13/1437');
+shouldBe(Intl.DateTimeFormat('en-u-ca-hebrew', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '13 Tevet 5776');
+shouldBe(Intl.DateTimeFormat('en-u-ca-indian', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '10/4/1937 Saka');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437 AH');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamicc', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/13/1437 AH');
 shouldBe(Intl.DateTimeFormat('en-u-ca-ISO8601', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/2015');
-shouldBe(Intl.DateTimeFormat('en-u-ca-japanese', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/27');
-shouldBe(Intl.DateTimeFormat('en-u-ca-persian', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '10/4/1394');
-shouldBe(Intl.DateTimeFormat('en-u-ca-roc', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/104');
-shouldBe(Intl.DateTimeFormat('en-u-ca-ethiopic-amete-alem', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/7508');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-umalqura', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-tbla', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-civil', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/13/1437');
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-rgsa', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437');
+shouldBe(Intl.DateTimeFormat('en-u-ca-japanese', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/27 H');
+shouldBe(Intl.DateTimeFormat('en-u-ca-persian', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '10/4/1394 AP');
+shouldBe(Intl.DateTimeFormat('en-u-ca-roc', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '12/25/104 Minguo');
+shouldBe(Intl.DateTimeFormat('en-u-ca-ethiopic-amete-alem', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '4/15/7508 ERA0');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-umalqura', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437 AH');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-tbla', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437 AH');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-civil', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/13/1437 AH');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-rgsa', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '3/14/1437 AH');
 
 shouldBe(Intl.DateTimeFormat('en', { numberingSystem: 'gujr' }).resolvedOptions().numberingSystem, 'gujr');
 shouldBe(Intl.DateTimeFormat('en-u-nu-bogus').resolvedOptions().locale, 'en');
@@ -386,7 +386,7 @@
 shouldBe(Intl.DateTimeFormat('en-u-hc-h24', { hour: 'numeric', timeZone: 'UTC' }).format(0), '24')
 
 // Tests multiple keys in extension.
-shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-umalqura-nu-arab', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '٣/١٤/١٤٣٧');
+shouldBe(Intl.DateTimeFormat('en-u-ca-islamic-umalqura-nu-arab', { timeZone: 'America/Los_Angeles' }).format(1451099872641), '٣/١٤/١٤٣٧ AH');
 
 shouldThrow(() => Intl.DateTimeFormat('en', { weekday: { toString() { throw new Error() } } }), Error);
 shouldThrow(() => Intl.DateTimeFormat('en', { weekday: 'invalid' }), RangeError);
@@ -634,3 +634,14 @@
         { type: 'timeZoneName', value: 'Pacific Standard Time' }
     ])
 );
+
+// Tests for relativeYear and yearName
+const parts = JSON.stringify([
+    { type: 'relatedYear', value: '1969' },
+    { type: 'yearName', value: '己酉' },
+    { type: 'literal', value: '年' }
+]);
+shouldBe(Intl.DateTimeFormat('zh-u-ca-chinese', { era: 'short', year: 'numeric' }).format(0), '1969己酉年');
+shouldBe(Intl.DateTimeFormat('zh', { era: 'short', year: 'numeric', calendar: 'chinese' }).format(0), '1969己酉年');
+shouldBe(JSON.stringify(Intl.DateTimeFormat('zh-u-ca-chinese', { era: 'short', year: 'numeric' }).formatToParts(0)), parts);
+shouldBe(JSON.stringify(Intl.DateTimeFormat('zh', { era: 'short', year: 'numeric', calendar: 'chinese' }).formatToParts(0)), parts);

Modified: trunk/JSTests/test262/config.yaml (260144 => 260145)


--- trunk/JSTests/test262/config.yaml	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/JSTests/test262/config.yaml	2020-04-15 19:51:24 UTC (rev 260145)
@@ -151,3 +151,8 @@
     # These tests timeout even with --timeout parameter set
     # https://bugs.webkit.org/show_bug.cgi?id=208639
     - test/built-ins/Array/prototype/lastIndexOf/length-near-integer-limit.js
+
+    # These tests require macOS system ICU to actually update its CLDR data >:(
+    # https://bugs.webkit.org/show_bug.cgi?id=209783
+    - test/intl402/DateTimeFormat/prototype/format/related-year-zh.js
+    - test/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js

Modified: trunk/JSTests/test262/expectations.yaml (260144 => 260145)


--- trunk/JSTests/test262/expectations.yaml	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/JSTests/test262/expectations.yaml	2020-04-15 19:51:24 UTC (rev 260145)
@@ -1923,18 +1923,6 @@
 test/intl402/DateTimeFormat/proto-from-ctor-realm.js:
   default: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Object]», «[object Object]») to be true'
   strict mode: 'Test262Error: newTarget.prototype is undefined Expected SameValue(«[object Object]», «[object Object]») to be true'
-test/intl402/DateTimeFormat/prototype/format/related-year-zh.js:
-  default: 'Test262Error: Expected SameValue(«36年», «2019己亥年») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«36年», «2019己亥年») to be true'
-test/intl402/DateTimeFormat/prototype/formatToParts/pattern-on-calendar.js:
-  default: 'Test262Error: Expected SameValue(«false», «true») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«false», «true») to be true'
-test/intl402/DateTimeFormat/prototype/formatToParts/related-year-zh.js:
-  default: 'Test262Error: undefined: length Expected SameValue(«2», «3») to be true'
-  strict mode: 'Test262Error: undefined: length Expected SameValue(«2», «3») to be true'
-test/intl402/DateTimeFormat/prototype/formatToParts/related-year.js:
-  default: 'Test262Error: Expected SameValue(«false», «true») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«false», «true») to be true'
 test/intl402/DateTimeFormat/prototype/resolvedOptions/hourCycle-default.js:
   default: 'Test262Error: Expected SameValue(«h24», «h23») to be true'
   strict mode: 'Test262Error: Expected SameValue(«h24», «h23») to be true'

Modified: trunk/Source/_javascript_Core/ChangeLog (260144 => 260145)


--- trunk/Source/_javascript_Core/ChangeLog	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-04-15 19:51:24 UTC (rev 260145)
@@ -1,3 +1,20 @@
+2020-04-15  Ross Kirsling  <ross.kirsl...@sony.com>
+
+        [ECMA-402] Fix Intl.DateTimeFormat patterns and fields in WebKit
+        https://bugs.webkit.org/show_bug.cgi?id=209783
+
+        Reviewed by Keith Miller.
+
+        This patch implements two intertwining normative changes to Intl.DateTimeFormat:
+          - Calendar setting must be taken into account when choosing a date-time pattern
+            https://github.com/tc39/ecma402/pull/349
+          - formatToParts must recognize relatedYear and yearName parts
+            https://github.com/tc39/ecma402/pull/349
+
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+        (JSC::IntlDateTimeFormat::partTypeString):
+
 2020-04-15  Devin Rousso  <drou...@apple.com>
 
         [ESNext] Implement logical assignment operators

Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp (260144 => 260145)


--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-04-15 19:42:57 UTC (rev 260144)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-04-15 19:51:24 UTC (rev 260145)
@@ -502,7 +502,7 @@
 
     m_hourCycle = resolved.get("hc"_s);
     m_numberingSystem = resolved.get("nu"_s);
-    String dataLocale = resolved.get("dataLocale"_s);
+    CString dataLocaleWithExtensions = makeString(resolved.get("dataLocale"_s), "-u-ca-", m_calendar, "-nu-", m_numberingSystem).utf8();
 
     JSValue tzValue = options->get(globalObject, vm.propertyNames->timeZone);
     RETURN_IF_EXCEPTION(scope, void());
@@ -631,7 +631,7 @@
 
     // Always use ICU date format generator, rather than our own pattern list and matcher.
     UErrorCode status = U_ZERO_ERROR;
-    UDateTimePatternGenerator* generator = udatpg_open(dataLocale.utf8().data(), &status);
+    UDateTimePatternGenerator* generator = udatpg_open(dataLocaleWithExtensions.data(), &status);
     if (U_FAILURE(status)) {
         throwTypeError(globalObject, scope, "failed to initialize DateTimeFormat"_s);
         return;
@@ -683,7 +683,7 @@
 
     status = U_ZERO_ERROR;
     StringView timeZoneView(m_timeZone);
-    m_dateFormat = std::unique_ptr<UDateFormat, UDateFormatDeleter>(udat_open(UDAT_PATTERN, UDAT_PATTERN, m_locale.utf8().data(), timeZoneView.upconvertedCharacters(), timeZoneView.length(), pattern.upconvertedCharacters(), pattern.length(), &status));
+    m_dateFormat = std::unique_ptr<UDateFormat, UDateFormatDeleter>(udat_open(UDAT_PATTERN, UDAT_PATTERN, dataLocaleWithExtensions.data(), timeZoneView.upconvertedCharacters(), timeZoneView.length(), pattern.upconvertedCharacters(), pattern.length(), &status));
     if (U_FAILURE(status)) {
         throwTypeError(globalObject, scope, "failed to initialize DateTimeFormat"_s);
         return;
@@ -932,9 +932,10 @@
     case UDAT_ERA_FIELD:
         return "era"_s;
     case UDAT_YEAR_FIELD:
-    case UDAT_YEAR_NAME_FIELD:
     case UDAT_EXTENDED_YEAR_FIELD:
         return "year"_s;
+    case UDAT_YEAR_NAME_FIELD:
+        return "yearName"_s;
     case UDAT_MONTH_FIELD:
     case UDAT_STANDALONE_MONTH_FIELD:
         return "month"_s;
@@ -966,6 +967,8 @@
     case UDAT_TIMEZONE_ISO_FIELD:
     case UDAT_TIMEZONE_ISO_LOCAL_FIELD:
         return "timeZoneName"_s;
+    case UDAT_RELATED_YEAR_FIELD:
+        return "relatedYear"_s;
     // These should not show up because there is no way to specify them in DateTimeFormat options.
     // If they do, they don't fit well into any of known part types, so consider it an "unknown".
     case UDAT_DAY_OF_YEAR_FIELD:
@@ -977,7 +980,6 @@
     case UDAT_MILLISECONDS_IN_DAY_FIELD:
     case UDAT_QUARTER_FIELD:
     case UDAT_STANDALONE_QUARTER_FIELD:
-    case UDAT_RELATED_YEAR_FIELD:
     case UDAT_TIME_SEPARATOR_FIELD:
     // Any newer additions to the UDateFormatField enum should just be considered an "unknown" part.
     default:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to