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 };