Title: [266170] trunk
Revision
266170
Author
[email protected]
Date
2020-08-26 09:48:33 -0700 (Wed, 26 Aug 2020)

Log Message

[JSC] Implement Intl.DateTimeFormat fractionalSecondDigits
https://bugs.webkit.org/show_bug.cgi?id=215840

Reviewed by Ross Kirsling.

JSTests:

Test262 is showing wrong ordering of option property accesses compared to the latest PR.
Later, we should update Test262.

* stress/intl-datetimeformat.js:
(const.options.get second):
(const.options.get fractionalSecondDigits):
(const.options.get localeMatcher):
(const.options.get timeZoneName):
(const.options.get formatMatcher):
* test262/config.yaml:
* test262/expectations.yaml:

Source/_javascript_Core:

This patch implements fractionalSecondDigits option for Intl.DateTimeFormat. If it is
specified, milliseconds in N digits are represented in the formatted output.
This extension is about to be merged into the spec[1]. SpiderMonkey and V8 support it,
and V8 shipped it without flags.

[1]: https://github.com/tc39/ecma402/pull/347

* builtins/DatePrototype.js:
(toLocaleString.toDateTimeOptionsAnyAll):
(toLocaleString):
(toLocaleTimeString.toDateTimeOptionsTimeTime):
(toLocaleTimeString):
* runtime/CommonIdentifiers.h:
* runtime/IntlDateTimeFormat.cpp:
(JSC::toDateTimeOptionsAnyDate):
(JSC::IntlDateTimeFormat::setFormatsFromPattern):
(JSC::IntlDateTimeFormat::initializeDateTimeFormat):
(JSC::IntlDateTimeFormat::resolvedOptions const):
(JSC::partTypeString):
* runtime/IntlDateTimeFormat.h:

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (266169 => 266170)


--- trunk/JSTests/ChangeLog	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/JSTests/ChangeLog	2020-08-26 16:48:33 UTC (rev 266170)
@@ -1,3 +1,22 @@
+2020-08-26  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Implement Intl.DateTimeFormat fractionalSecondDigits
+        https://bugs.webkit.org/show_bug.cgi?id=215840
+
+        Reviewed by Ross Kirsling.
+
+        Test262 is showing wrong ordering of option property accesses compared to the latest PR.
+        Later, we should update Test262.
+
+        * stress/intl-datetimeformat.js:
+        (const.options.get second):
+        (const.options.get fractionalSecondDigits):
+        (const.options.get localeMatcher):
+        (const.options.get timeZoneName):
+        (const.options.get formatMatcher):
+        * test262/config.yaml:
+        * test262/expectations.yaml:
+
 2020-08-26  Paulo Matos  <[email protected]>
 
         Skip stress/array-species-create-should-handle-masquerader.js on MIPS

Modified: trunk/JSTests/stress/intl-datetimeformat.js (266169 => 266170)


--- trunk/JSTests/stress/intl-datetimeformat.js	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/JSTests/stress/intl-datetimeformat.js	2020-08-26 16:48:33 UTC (rev 266170)
@@ -660,3 +660,85 @@
 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);
+
+{
+    let t = new Date("2019-05-20T07:00:23.123");
+    {
+        let dtf = new Intl.DateTimeFormat("en", {hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 3});
+        shouldBe(dtf.format(t), `7:00:23.123 AM`);
+        let expected = [
+            {type: "hour", value: "7"},
+            {type: "literal", value: ":"},
+            {type: "minute", value: "00"},
+            {type: "literal", value: ":"},
+            {type: "second", value: "23"},
+            {type: "literal", value: "."},
+            {type: "fractionalSecond", value: "123"},
+            {type: "literal", value: " "},
+            {type: "dayPeriod", value: "AM"}
+        ];
+        let actual = dtf.formatToParts(t);
+        shouldBe(actual.length, expected.length);
+        for (let index = 0; index < expected.length; ++index) {
+            shouldBe(actual[index].type, expected[index].type);
+            shouldBe(actual[index].value, expected[index].value);
+        }
+    }
+    {
+        let dtf = new Intl.DateTimeFormat("en", {hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 2});
+        shouldBe(dtf.format(t), `7:00:23.12 AM`);
+    }
+    {
+        let dtf = new Intl.DateTimeFormat("en", {hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 1});
+        shouldBe(dtf.format(t), `7:00:23.1 AM`);
+        shouldBe(JSON.stringify(dtf.resolvedOptions()), `{"locale":"en","calendar":"gregory","numberingSystem":"latn","timeZone":"America/Los_Angeles","hourCycle":"h12","hour12":true,"hour":"numeric","minute":"2-digit","second":"2-digit","fractionalSecondDigits":1}`);
+    }
+    shouldThrow(() => {
+        new Intl.DateTimeFormat("en", {hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 0});
+    }, RangeError);
+    shouldThrow(() => {
+        new Intl.DateTimeFormat("en", {hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 4});
+    }, RangeError);
+}
+{
+    const expected = [
+      "second",
+      "fractionalSecondDigits",
+      "localeMatcher",
+      "second",
+      "fractionalSecondDigits",
+      "timeZoneName",
+      "formatMatcher",
+    ];
+
+    const actual = [];
+
+    const options = {
+      get second() {
+        actual.push("second");
+        return "numeric";
+      },
+      get fractionalSecondDigits() {
+        actual.push("fractionalSecondDigits");
+        return undefined;
+      },
+      get localeMatcher() {
+        actual.push("localeMatcher");
+        return undefined;
+      },
+      get timeZoneName() {
+        actual.push("timeZoneName");
+        return undefined;
+      },
+      get formatMatcher() {
+        actual.push("formatMatcher");
+        return undefined;
+      },
+    };
+
+    new Intl.DateTimeFormat("en", options);
+    shouldBe(JSON.stringify(actual), JSON.stringify(expected));
+}
+{
+    shouldBe(new Date(0).toLocaleTimeString('zh-Hans-CN', { timeZone: 'UTC', numberingSystem: 'hanidec', hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 2 }), "上午一二:〇〇:〇〇.〇〇");
+}

Modified: trunk/JSTests/test262/config.yaml (266169 => 266170)


--- trunk/JSTests/test262/config.yaml	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/JSTests/test262/config.yaml	2020-08-26 16:48:33 UTC (rev 266170)
@@ -25,7 +25,6 @@
     - regexp-match-indices
     - top-level-await
     - Intl.DateTimeFormat-dayPeriod
-    - Intl.DateTimeFormat-fractionalSecondDigits
     - Intl.ListFormat
   paths:
     - test/built-ins/DataView/prototype/getBigInt64

Modified: trunk/JSTests/test262/expectations.yaml (266169 => 266170)


--- trunk/JSTests/test262/expectations.yaml	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/JSTests/test262/expectations.yaml	2020-08-26 16:48:33 UTC (rev 266170)
@@ -1551,6 +1551,9 @@
 test/intl402/Collator/missing-unicode-ext-value-defaults-to-true.js:
   default: "Test262Error: \"kn-true\" is returned in locale, but shouldn't be. Expected SameValue(«7», «-1») to be true"
   strict mode: "Test262Error: \"kn-true\" is returned in locale, but shouldn't be. Expected SameValue(«7», «-1») to be true"
+test/intl402/DateTimeFormat/constructor-options-order-fractionalSecondDigits.js:
+  default: 'Test262Error: Expected [second, fractionalSecondDigits, localeMatcher, second, fractionalSecondDigits, timeZoneName, formatMatcher] and [second, fractionalSecondDigits, localeMatcher, second, timeZoneName, fractionalSecondDigits, formatMatcher] to have the same contents. '
+  strict mode: 'Test262Error: Expected [second, fractionalSecondDigits, localeMatcher, second, fractionalSecondDigits, timeZoneName, formatMatcher] and [second, fractionalSecondDigits, localeMatcher, second, timeZoneName, fractionalSecondDigits, formatMatcher] to have the same contents. '
 test/intl402/DateTimeFormat/prototype/format/timedatestyle-en.js:
   default: 'Test262Error: Result for full with {} Expected SameValue(«14:12:47 PM Coordinated Universal Time», «14:12:47 Coordinated Universal Time») to be true'
   strict mode: 'Test262Error: Result for full with {} Expected SameValue(«14:12:47 PM Coordinated Universal Time», «14:12:47 Coordinated Universal Time») to be true'
@@ -1557,6 +1560,9 @@
 test/intl402/DateTimeFormat/prototype/formatRange/en-US.js:
   default: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true'
   strict mode: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true'
+test/intl402/DateTimeFormat/prototype/formatRange/fractionalSecondDigits.js:
+  default: 'Test262Error: no fractionalSecondDigits Expected SameValue(«02:03 – 02:13», «02:03 – 02:13») to be true'
+  strict mode: 'Test262Error: no fractionalSecondDigits Expected SameValue(«02:03 – 02:13», «02:03 – 02:13») 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 (266169 => 266170)


--- trunk/Source/_javascript_Core/ChangeLog	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-08-26 16:48:33 UTC (rev 266170)
@@ -1,3 +1,31 @@
+2020-08-26  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Implement Intl.DateTimeFormat fractionalSecondDigits
+        https://bugs.webkit.org/show_bug.cgi?id=215840
+
+        Reviewed by Ross Kirsling.
+
+        This patch implements fractionalSecondDigits option for Intl.DateTimeFormat. If it is
+        specified, milliseconds in N digits are represented in the formatted output.
+        This extension is about to be merged into the spec[1]. SpiderMonkey and V8 support it,
+        and V8 shipped it without flags.
+
+        [1]: https://github.com/tc39/ecma402/pull/347
+
+        * builtins/DatePrototype.js:
+        (toLocaleString.toDateTimeOptionsAnyAll):
+        (toLocaleString):
+        (toLocaleTimeString.toDateTimeOptionsTimeTime):
+        (toLocaleTimeString):
+        * runtime/CommonIdentifiers.h:
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::toDateTimeOptionsAnyDate):
+        (JSC::IntlDateTimeFormat::setFormatsFromPattern):
+        (JSC::IntlDateTimeFormat::initializeDateTimeFormat):
+        (JSC::IntlDateTimeFormat::resolvedOptions const):
+        (JSC::partTypeString):
+        * runtime/IntlDateTimeFormat.h:
+
 2020-08-25  Yusuke Suzuki  <[email protected]>
 
         [JSC] FTL should use m_origin instead of m_node->origin since m_node can be nullptr

Modified: trunk/Source/_javascript_Core/builtins/DatePrototype.js (266169 => 266170)


--- trunk/Source/_javascript_Core/builtins/DatePrototype.js	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/Source/_javascript_Core/builtins/DatePrototype.js	2020-08-26 16:48:33 UTC (rev 266170)
@@ -48,7 +48,8 @@
             options.day === @undefined &&
             options.hour === @undefined &&
             options.minute === @undefined &&
-            options.second === @undefined
+            options.second === @undefined &&
+            options.fractionalSecondDigits === @undefined
         );
 
         if (options) {
@@ -163,7 +164,8 @@
         var needsDefaults = !options || (
             options.hour === @undefined &&
             options.minute === @undefined &&
-            options.second === @undefined
+            options.second === @undefined &&
+            options.fractionalSecondDigits === @undefined
         );
 
         if (options) {

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (266169 => 266170)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2020-08-26 16:48:33 UTC (rev 266170)
@@ -116,6 +116,7 @@
     macro(formatMatcher) \
     macro(formatToParts) \
     macro(forward) \
+    macro(fractionalSecondDigits) \
     macro(from) \
     macro(fromCharCode) \
     macro(get) \

Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp (266169 => 266170)


--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.cpp	2020-08-26 16:48:33 UTC (rev 266170)
@@ -248,7 +248,7 @@
     // 6. If required is "time" or "any",
     // Always "any".
 
-    // a. For each of the property names "hour", "minute", "second":
+    // a. For each of the property names "hour", "minute", "second", "fractionalSecondDigits":
     // i. Let prop be the property name.
     // ii. Let value be Get(options, prop).
     // iii. ReturnIfAbrupt(value).
@@ -268,6 +268,11 @@
     if (!second.isUndefined())
         needDefaults = false;
 
+    JSValue fractionalSecondDigits = options->get(globalObject, vm.propertyNames->fractionalSecondDigits);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    if (!fractionalSecondDigits.isUndefined())
+        needDefaults = false;
+
     JSValue dateStyle = options->get(globalObject, vm.propertyNames->dateStyle);
     RETURN_IF_EXCEPTION(scope, nullptr);
     JSValue timeStyle = options->get(globalObject, vm.propertyNames->timeStyle);
@@ -402,6 +407,9 @@
             else if (count == 4)
                 m_timeZoneName = TimeZoneName::Long;
             break;
+        case 'S':
+            m_fractionalSecondDigits = count;
+            break;
         }
     }
 }
@@ -625,6 +633,11 @@
         break;
     }
 
+    unsigned fractionalSecondDigits = intlNumberOption(globalObject, options, vm.propertyNames->fractionalSecondDigits, 1, 3, 0);
+    RETURN_IF_EXCEPTION(scope, void());
+    for (unsigned i = 0; i < fractionalSecondDigits; ++i)
+        skeletonBuilder.append('S');
+
     TimeZoneName timeZoneName = intlOption<TimeZoneName>(globalObject, options, vm.propertyNames->timeZoneName, { { "short"_s, TimeZoneName::Short }, { "long"_s, TimeZoneName::Long } }, "timeZoneName must be \"short\" or \"long\""_s, TimeZoneName::None);
     RETURN_IF_EXCEPTION(scope, void());
     switch (timeZoneName) {
@@ -655,7 +668,7 @@
         //     ii. Let p be opt.[[<prop>]].
         //     iii. If p is not undefined, then
         //         1. Throw a TypeError exception.
-        if (weekday != Weekday::None || era != Era::None || year != Year::None || month != Month::None || day != Day::None || hour != Hour::None || minute != Minute::None || second != Second::None || timeZoneName != TimeZoneName::None) {
+        if (weekday != Weekday::None || era != Era::None || year != Year::None || month != Month::None || day != Day::None || hour != Hour::None || minute != Minute::None || second != Second::None || fractionalSecondDigits != 0 || timeZoneName != TimeZoneName::None) {
             throwTypeError(globalObject, scope, "dateStyle and timeStyle may not be used with other DateTimeFormat options"_s);
             return;
         }
@@ -998,6 +1011,9 @@
     if (m_second != Second::None)
         options->putDirect(vm, vm.propertyNames->second, jsNontrivialString(vm, secondString(m_second)));
 
+    if (m_fractionalSecondDigits)
+        options->putDirect(vm, vm.propertyNames->fractionalSecondDigits, jsNumber(m_fractionalSecondDigits));
+
     if (m_timeZoneName != TimeZoneName::None)
         options->putDirect(vm, vm.propertyNames->timeZoneName, jsNontrivialString(vm, timeZoneNameString(m_timeZoneName)));
 
@@ -1052,8 +1068,9 @@
     case UDAT_MINUTE_FIELD:
         return "minute"_s;
     case UDAT_SECOND_FIELD:
+        return "second"_s;
     case UDAT_FRACTIONAL_SECOND_FIELD:
-        return "second"_s;
+        return "fractionalSecond"_s;
     case UDAT_DAY_OF_WEEK_FIELD:
     case UDAT_DOW_LOCAL_FIELD:
     case UDAT_STANDALONE_DAY_FIELD:

Modified: trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h (266169 => 266170)


--- trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h	2020-08-26 16:46:04 UTC (rev 266169)
+++ trunk/Source/_javascript_Core/runtime/IntlDateTimeFormat.h	2020-08-26 16:48:33 UTC (rev 266170)
@@ -120,6 +120,7 @@
     Hour m_hour { Hour::None };
     Minute m_minute { Minute::None };
     Second m_second { Second::None };
+    uint8_t m_fractionalSecondDigits { 0 };
     TimeZoneName m_timeZoneName { TimeZoneName::None };
     DateTimeStyle m_dateStyle { DateTimeStyle::None };
     DateTimeStyle m_timeStyle { DateTimeStyle::None };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to