Skip to content
Permalink
Browse files
Implement with and round methods for TemporalPlainDate[Time]
https://bugs.webkit.org/show_bug.cgi?id=245282

Reviewed by Yusuke Suzuki.

This patch implements the following Temporal API methods:
  - PlainDate.prototype.with
  - PlainDateTime.prototype.{with, withPlainDate, withPlainTime, round}

Note: `with` will likely need significant refactoring in the future. At present, the spec demands bafflingly inefficient
behavior, observably calling out to Calendar multiple times and creating multiple intermediate JSObjects, even in the
default case where the user is not making conscious use of Calendar at all. This is a showstopper, but one which Yusuke
already reported in tc39/proposal-temporal#1808.

* JSTests/stress/temporal-plaindate.js:
* JSTests/stress/temporal-plaindatetime.js:
* JSTests/test262/config.yaml:
* JSTests/test262/expectations.yaml:
* Source/JavaScriptCore/runtime/TemporalCalendar.cpp:
(JSC::TemporalCalendar::from):
(JSC::TemporalCalendar::isoDateFromFields): Split into two.
* Source/JavaScriptCore/runtime/TemporalCalendar.h:
* Source/JavaScriptCore/runtime/TemporalObject.cpp:
(JSC::rejectObjectWithCalendarOrTimeZone): Added.
* Source/JavaScriptCore/runtime/TemporalObject.h:
* Source/JavaScriptCore/runtime/TemporalPlainDate.cpp:
(JSC::TemporalPlainDate::toPartialDate): Added.
(JSC::TemporalPlainDate::with): Added.
* Source/JavaScriptCore/runtime/TemporalPlainDate.h:
* Source/JavaScriptCore/runtime/TemporalPlainDatePrototype.cpp:
* Source/JavaScriptCore/runtime/TemporalPlainDateTime.cpp:
(JSC::TemporalPlainDateTime::with): Added.
(JSC::TemporalPlainDateTime::round): Added.
* Source/JavaScriptCore/runtime/TemporalPlainDateTime.h:
* Source/JavaScriptCore/runtime/TemporalPlainDateTimePrototype.cpp:
* Source/JavaScriptCore/runtime/TemporalPlainTime.cpp:
(JSC::TemporalPlainTime::roundTime):
(JSC::TemporalPlainTime::toTemporalTimeRecord):
(JSC::TemporalPlainTime::toPartialTime):
(JSC::TemporalPlainTime::with const):
(JSC::toPartialTime): Made public static.
* Source/JavaScriptCore/runtime/TemporalPlainTime.h:

Canonical link: https://commits.webkit.org/254565@main
  • Loading branch information
rkirsling committed Sep 16, 2022
1 parent c096c71 commit 2f0cbc36b53452d3befb58be7e204dfd0f557cf0
Show file tree
Hide file tree
Showing 16 changed files with 462 additions and 38 deletions.
@@ -353,8 +353,8 @@ shouldThrow(() => { Temporal.PlainDate.from('2007-01-09').valueOf(); }, TypeErro
shouldBe(ones.equals(new Temporal.PlainDate(1,1,2)), false);
}

shouldBe(Temporal.PlainDateTime.prototype.add.length, 1);
shouldBe(Temporal.PlainDateTime.prototype.subtract.length, 1);
shouldBe(Temporal.PlainDate.prototype.add.length, 1);
shouldBe(Temporal.PlainDate.prototype.subtract.length, 1);
{
const date = Temporal.PlainDate.from('2020-02-28');
shouldBe(date.add(new Temporal.Duration()).toString(), '2020-02-28');
@@ -377,3 +377,11 @@ shouldBe(Temporal.PlainDateTime.prototype.subtract.length, 1);
shouldThrow(() => { Temporal.PlainDate.from('2020-03-30').subtract({ months: 1 }, { overflow: 'reject' }); }, RangeError);
shouldThrow(() => { date.subtract({ years: 300000 }); }, RangeError);
}

shouldBe(Temporal.PlainDate.prototype.with.length, 1);
{
const date = new Temporal.PlainDate(2020,1,30);
shouldBe(date.with({ year: 2021, month: 3, day: 5 }).toString(), '2021-03-05');
shouldBe(date.with({ month: 2 }).toString(), '2020-02-29');
shouldThrow(() => { date.with({ month: 2 }, { overflow: 'reject' }); }, RangeError);
}
@@ -270,3 +270,27 @@ shouldBe(pdt.subtract(new Temporal.Duration(0,1,5,3,4,5,6,7,8,10)).toString(), '
shouldBe(Temporal.PlainDateTime.from('2020-03-30').subtract({ months: 1 }).toString(), '2020-02-29T00:00:00');
shouldThrow(() => { Temporal.PlainDateTime.from('2020-03-30').subtract({ months: 1 }, { overflow: 'reject' }); }, RangeError);
shouldThrow(() => { pdt.subtract({ years: 300000 }); }, RangeError);

shouldBe(Temporal.PlainDateTime.prototype.with.length, 1);
shouldBe(pdt.with({ year: 2000, month: 10, hour: 1, minute: 3, millisecond: 0, microsecond: 0, nanosecond: 0 }).toString(), '2000-10-03T01:03:06');
shouldBe(pdt.with({ second: 15 }).toString(), '0001-02-03T04:05:15.007008009');
shouldBe(pdt.with({ day: 30 }).toString(), '0001-02-28T04:05:06.007008009');
shouldThrow(() => { pdt.with({ day: 30 }, { overflow: 'reject' }); }, RangeError);

shouldBe(Temporal.PlainDateTime.prototype.withPlainDate.length, 1);
shouldThrow(() => { pdt.withPlainDate(); }, RangeError);
shouldBe(pdt.withPlainDate({ year: 2000, month: 10, day: 30 }).toString(), '2000-10-30T04:05:06.007008009');

shouldBe(Temporal.PlainDateTime.prototype.withPlainTime.length, 0);
shouldBe(pdt.withPlainTime().toString(), '0001-02-03T00:00:00');
shouldBe(pdt.withPlainTime({ hour: 1, minute: 2, second: 3 }).toString(), '0001-02-03T01:02:03');

shouldBe(Temporal.PlainDateTime.prototype.round.length, 1);
shouldBe(pdt.round('hour').toString(), '0001-02-03T04:00:00');
shouldBe(pdt.round({ smallestUnit: 'hour' }).toString(), '0001-02-03T04:00:00');
shouldBe(pdt.round({ smallestUnit: 'minute', roundingIncrement: 2 }).toString(), '0001-02-03T04:06:00');
shouldBe(pdt.round({ smallestUnit: 'minute', roundingIncrement: 2, roundingMode: 'floor' }).toString(), '0001-02-03T04:04:00');
shouldThrow(() => { pdt.round({}); }, RangeError);
shouldThrow(() => { pdt.round({ smallestUnit: 'bogus' }); }, RangeError);
shouldThrow(() => { pdt.round({ smallestUnit: 'minute', roundingIncrement: 24 }); }, RangeError);
shouldThrow(() => { pdt.round({ smallestUnit: 'minute', roundingMode: 'bogus' }); }, RangeError);
@@ -41,18 +41,13 @@ skip:
- test/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth
- test/built-ins/Temporal/PlainDate/prototype/toZonedDateTime
- test/built-ins/Temporal/PlainDate/prototype/until
- test/built-ins/Temporal/PlainDate/prototype/with
- test/built-ins/Temporal/PlainDate/prototype/withCalendar
- test/built-ins/Temporal/PlainDateTime/prototype/round
- test/built-ins/Temporal/PlainDateTime/prototype/since
- test/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay
- test/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth
- test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime
- test/built-ins/Temporal/PlainDateTime/prototype/until
- test/built-ins/Temporal/PlainDateTime/prototype/with
- test/built-ins/Temporal/PlainDateTime/prototype/withCalendar
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime
- test/built-ins/Temporal/PlainMonthDay
- test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime
- test/built-ins/Temporal/PlainYearMonth
@@ -423,6 +418,13 @@ skip:
- test/built-ins/Temporal/PlainDate/prototype/toString/calendarname-wrong-type.js
- test/built-ins/Temporal/PlainDate/prototype/toString/options-undefined.js
- test/built-ins/Temporal/PlainDate/prototype/weekOfYear/custom.js
- test/built-ins/Temporal/PlainDate/prototype/with/calendar-fields-iterable.js
- test/built-ins/Temporal/PlainDate/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
- test/built-ins/Temporal/PlainDate/prototype/with/calendar-invalid-return.js
- test/built-ins/Temporal/PlainDate/prototype/with/calendar-merge-fields-returns-primitive.js
- test/built-ins/Temporal/PlainDate/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
- test/built-ins/Temporal/PlainDate/prototype/with/copies-merge-fields-object.js
- test/built-ins/Temporal/PlainDate/prototype/with/custom.js
- test/built-ins/Temporal/PlainDate/prototype/year/calendar-returns-infinity.js
- test/built-ins/Temporal/PlainDateTime/calendar-number.js
- test/built-ins/Temporal/PlainDateTime/calendar-temporal-object.js
@@ -462,6 +464,8 @@ skip:
- test/built-ins/Temporal/PlainDateTime/prototype/inLeapYear/custom.js
- test/built-ins/Temporal/PlainDateTime/prototype/month/calendar-returns-infinity.js
- test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/custom.js
- test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-plurals-accepted.js
- test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-string-shorthand.js
- test/built-ins/Temporal/PlainDateTime/prototype/subtract/calendar-dateadd.js
- test/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-always.js
- test/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-auto.js
@@ -471,6 +475,28 @@ skip:
- test/built-ins/Temporal/PlainDateTime/prototype/toString/calendarname-wrong-type.js
- test/built-ins/Temporal/PlainDateTime/prototype/toString/options-undefined.js
- test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/custom.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fields-iterable.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-merge-fields-returns-primitive.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-options.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws.js
- test/built-ins/Temporal/PlainDateTime/prototype/with/copies-merge-fields-object.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-calendar-datefromfields-called-with-null-prototype-fields.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-noniso.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-id.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-object.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-propertybag-calendar-leap-second.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-propertybag-calendar-number.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-propertybag-calendar-wrong-type.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-fields-iterable.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-temporal-object.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/calendar-temporal-object.js
- test/built-ins/Temporal/PlainDateTime/prototype/year/calendar-returns-infinity.js
- test/built-ins/Temporal/PlainTime/compare/calendar-temporal-object.js
- test/built-ins/Temporal/PlainTime/from/argument-string-with-calendar.js
@@ -494,6 +520,7 @@ skip:
- test/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string.js
- test/built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted.js
- test/built-ins/Temporal/Instant/prototype/toString/smallestunit-plurals-accepted.js
- test/built-ins/Temporal/PlainDate/prototype/with/plaindatelike-invalid.js
- test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-plurals-accepted.js
- test/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js
- test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js
@@ -601,6 +628,18 @@ skip:
- test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
- test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
- test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-convert.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-slots.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-negative-epochnanoseconds.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
- test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js
- test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js
- test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
- test/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
@@ -831,6 +831,12 @@ test/built-ins/Temporal/PlainDateTime/datetime-math.js:
test/built-ins/Temporal/PlainDateTime/from/order-of-operations.js:
default: 'Test262Error: Expected [get calendar, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get day, get day.valueOf, call day.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get year, get year.valueOf, call year.valueOf] and [get calendar, get day, get day.valueOf, call day.valueOf, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get year, get year.valueOf, call year.valueOf] to have the same contents. order of operations'
strict mode: 'Test262Error: Expected [get calendar, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get day, get day.valueOf, call day.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get year, get year.valueOf, call year.valueOf] and [get calendar, get day, get day.valueOf, call day.valueOf, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get year, get year.valueOf, call year.valueOf] to have the same contents. order of operations'
test/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js:
default: 'Test262Error: Expected [get calendar, get timeZone, get day, get day.valueOf, call day.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get year, get year.valueOf, call year.valueOf, get options.overflow, get options.overflow.toString, call options.overflow.toString, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf] and [get calendar, get timeZone, get day, get day.valueOf, call day.valueOf, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get year, get year.valueOf, call year.valueOf, get options.overflow, get options.overflow.toString, call options.overflow.toString, get options.overflow, get options.overflow.toString, call options.overflow.toString] to have the same contents. order of operations'
strict mode: 'Test262Error: Expected [get calendar, get timeZone, get day, get day.valueOf, call day.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get year, get year.valueOf, call year.valueOf, get options.overflow, get options.overflow.toString, call options.overflow.toString, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf] and [get calendar, get timeZone, get day, get day.valueOf, call day.valueOf, get hour, get hour.valueOf, call hour.valueOf, get microsecond, get microsecond.valueOf, call microsecond.valueOf, get millisecond, get millisecond.valueOf, call millisecond.valueOf, get minute, get minute.valueOf, call minute.valueOf, get month, get month.valueOf, call month.valueOf, get monthCode, get monthCode.toString, call monthCode.toString, get nanosecond, get nanosecond.valueOf, call nanosecond.valueOf, get second, get second.valueOf, call second.valueOf, get year, get year.valueOf, call year.valueOf, get options.overflow, get options.overflow.toString, call options.overflow.toString, get options.overflow, get options.overflow.toString, call options.overflow.toString] to have the same contents. order of operations'
test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-wrong-type.js:
default: 'Test262Error: Expected [get overflow.toString, call overflow.toString] and [get overflow.toString, call overflow.toString, get overflow.toString, call overflow.toString] to have the same contents. order of operations'
strict mode: 'Test262Error: Expected [get overflow.toString, call overflow.toString] and [get overflow.toString, call overflow.toString, get overflow.toString, call overflow.toString] to have the same contents. order of operations'
test/built-ins/Temporal/getOwnPropertyNames.js:
default: 'Test262Error: ZonedDateTime'
strict mode: 'Test262Error: ZonedDateTime'

0 comments on commit 2f0cbc3

Please sign in to comment.