From 8c57d679e2de3e7674173e6eb3a30c8350632f8b Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Wed, 4 Dec 2024 17:35:08 -0800 Subject: [PATCH 1/6] Editorial: Avoid hitting assertion in DifferenceISODateTime DifferenceISODateTime asserts that the ISO Date-Time Records passed to it are within limits. Previously there were two places where this was not guaranteed to be the case. Add checks that throw RangeError so the assertion is not hit. Closes: #3015 --- polyfill/lib/ecmascript.mjs | 4 ++++ polyfill/test262 | 2 +- spec/plaindatetime.html | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 6d256e2dd..31d9ea838 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -3479,6 +3479,8 @@ export function DifferencePlainDateTimeWithRounding( return { date: ZeroDateDuration(), time: TimeDuration.ZERO }; } + RejectDateTimeRange(isoDateTime1); + RejectDateTimeRange(isoDateTime2); const duration = DifferenceISODateTime(isoDateTime1, isoDateTime2, calendar, largestUnit); if (smallestUnit === 'nanosecond' && roundingIncrement === 1) return duration; @@ -3500,6 +3502,8 @@ export function DifferencePlainDateTimeWithRounding( export function DifferencePlainDateTimeWithTotal(isoDateTime1, isoDateTime2, calendar, unit) { if (CompareISODateTime(isoDateTime1, isoDateTime2) == 0) return 0; + RejectDateTimeRange(isoDateTime1); + RejectDateTimeRange(isoDateTime2); const duration = DifferenceISODateTime(isoDateTime1, isoDateTime2, calendar, unit); if (unit === 'nanosecond') return duration.time.totalNs.toJSNumber(); diff --git a/polyfill/test262 b/polyfill/test262 index 42d83277b..eefc5cf36 160000 --- a/polyfill/test262 +++ b/polyfill/test262 @@ -1 +1 @@ -Subproject commit 42d83277b7d73ea7b6e28a9ddedf8f4b2cee0d50 +Subproject commit eefc5cf367b999768445432e167606fd1acf1734 diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html index 8cf10019c..06fa04712 100644 --- a/spec/plaindatetime.html +++ b/spec/plaindatetime.html @@ -1001,6 +1001,7 @@

1. If CompareISODateTime(_isoDateTime1_, _isoDateTime2_) = 0, then 1. Return CombineDateAndTimeDuration(ZeroDateDuration(), 0). + 1. If ISODateTimeWithinLimits(_isoDateTime1_) is *false* or ISODateTimeWithinLimits(_isoDateTime2_) is *false*, throw a *RangeError* exception. 1. Let _diff_ be DifferenceISODateTime(_isoDateTime1_, _isoDateTime2_, _calendar_, _largestUnit_). 1. If _smallestUnit_ is ~nanosecond~ and _roundingIncrement_ = 1, return _diff_. 1. Let _destEpochNs_ be GetUTCEpochNanoseconds(_isoDateTime2_). @@ -1024,6 +1025,7 @@

1. If CompareISODateTime(_isoDateTime1_, _isoDateTime2_) = 0, then 1. Return 0. + 1. If ISODateTimeWithinLimits(_isoDateTime1_) is *false* or ISODateTimeWithinLimits(_isoDateTime2_) is *false*, throw a *RangeError* exception. 1. Let _diff_ be DifferenceISODateTime(_isoDateTime1_, _isoDateTime2_, _calendar_, _unit_). 1. If _unit_ is ~nanosecond~, return _diff_.[[Time]]. 1. Let _destEpochNs_ be GetUTCEpochNanoseconds(_isoDateTime2_). From ecd023296a76a8f568da4cddced2b54a0213e5eb Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 5 Dec 2024 11:11:12 -0800 Subject: [PATCH 2/6] Editorial: Fix incorrect pluralization and punctuation in description --- spec/intl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/intl.html b/spec/intl.html index 4cca78064..c3e4547f9 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -1651,7 +1651,7 @@

).

From e88318acb6dfb4dc5ddc5a7c87e5f9ba82a99ed6 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 5 Dec 2024 12:52:25 -0800 Subject: [PATCH 3/6] Editorial: Simplify anyPresent condition --- spec/intl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/intl.html b/spec/intl.html index c3e4547f9..9f1f2d648 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -864,8 +864,8 @@

1. If _value_ is not *undefined*, then 1. Set _formatOptions_.[[<_prop_>]] to _value_. 1. Set _needDefaults_ to *false*. - 1. If _anyPresent_ is *true* and _needDefaults_ is *true*, return *null*. 1. If _needDefaults_ is *true*, then + 1. If _anyPresent_ is *true*, return *null*. 1. For each property name _prop_ of _defaultOptions_, do 1. Set _formatOptions_.[[<_prop_>]] to *"numeric"*. 1. If _defaults_ is ~zoned-date-time~, then From 20fd580f8cfc4d27f93aedffe118846273e7c9be Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 5 Dec 2024 13:11:56 -0800 Subject: [PATCH 4/6] Polyfill: Fix util.inspect output of polyfilled Intl.DateTimeFormat The default formatter would look for a property called _repr_, which does not exist, and therefore would be confusingly formatted as "undefined". Instead, delegate to the original Intl.DateTimeFormat's util.inspect output. --- polyfill/lib/intl.mjs | 2 +- polyfill/lib/intrinsicclass.mjs | 4 ++++ polyfill/lib/slots.mjs | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/polyfill/lib/intl.mjs b/polyfill/lib/intl.mjs index 4fff61806..767548f0d 100644 --- a/polyfill/lib/intl.mjs +++ b/polyfill/lib/intl.mjs @@ -30,6 +30,7 @@ import { EPOCHNANOSECONDS, ISO_DATE, ISO_DATE_TIME, + ORIGINAL, SetSlot, TIME, CALENDAR @@ -41,7 +42,6 @@ const MD = SymbolCtor('md'); const TIME_FMT = SymbolCtor('time'); const DATETIME = SymbolCtor('datetime'); const INST = SymbolCtor('instant'); -const ORIGINAL = SymbolCtor('original'); const TZ_CANONICAL = SymbolCtor('timezone-canonical'); const TZ_ORIGINAL = SymbolCtor('timezone-original'); const CAL_ID = SymbolCtor('calendar-id'); diff --git a/polyfill/lib/intrinsicclass.mjs b/polyfill/lib/intrinsicclass.mjs index d4906dd2c..1e24f8174 100644 --- a/polyfill/lib/intrinsicclass.mjs +++ b/polyfill/lib/intrinsicclass.mjs @@ -9,6 +9,7 @@ import { SymbolFor, SymbolToStringTag } from './primordials.mjs'; +import { GetSlot, ORIGINAL } from './slots.mjs'; import Call from 'es-abstract/2024/Call.js'; @@ -17,6 +18,9 @@ import ESGetIntrinsic from 'es-abstract/GetIntrinsic.js'; const INTRINSICS = {}; const customUtilInspectFormatters = { + ['Intl.DateTimeFormat'](depth, options, inspect) { + return inspect(GetSlot(this, ORIGINAL), { depth, ...options }); + }, ['Temporal.Duration'](depth, options) { const descr = options.stylize(this._repr_, 'special'); if (depth < 1) return descr; diff --git a/polyfill/lib/slots.mjs b/polyfill/lib/slots.mjs index 16962e509..0898c8bf0 100644 --- a/polyfill/lib/slots.mjs +++ b/polyfill/lib/slots.mjs @@ -38,6 +38,9 @@ export const MILLISECONDS = 'slot-milliseconds'; export const MICROSECONDS = 'slot-microseconds'; export const NANOSECONDS = 'slot-nanoseconds'; +// Intl.DateTimeFormat +export const ORIGINAL = 'slot-original'; + const slots = new WeakMapCtor(); export function CreateSlots(container) { Call(WeakMapPrototypeSet, slots, [container, ObjectCreate(null)]); From 1f510736deff7ed59798164457a064b8f7ccfa8c Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 5 Dec 2024 13:32:12 -0800 Subject: [PATCH 5/6] Editorial: Avoid hitting nonnull assertion for bestFormat In a94a793 the desired behaviour when formatting Temporal objects was accidentally applied to formatting Date objects. So new Date().toLocaleDateString([], { hour: "numeric" }); would result in bestFormat being null, and according to the type assertion of the Intl.DateTimeFormat [[DateTimeFormat]] internal slot, that is not possible. Checking that _inherit_ = ~relevant~ here ensures the new behaviour is only applied to Temporal objects, and the type assertion is not hit. See: #3049 --- spec/intl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/intl.html b/spec/intl.html index 9f1f2d648..13ded2a18 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -865,7 +865,7 @@

1. Set _formatOptions_.[[<_prop_>]] to _value_. 1. Set _needDefaults_ to *false*. 1. If _needDefaults_ is *true*, then - 1. If _anyPresent_ is *true*, return *null*. + 1. If _anyPresent_ is *true* and _inherit_ is ~relevant~, return *null*. 1. For each property name _prop_ of _defaultOptions_, do 1. Set _formatOptions_.[[<_prop_>]] to *"numeric"*. 1. If _defaults_ is ~zoned-date-time~, then From 78a10fe88102510cf774d432333e09f9d0f15774 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 5 Dec 2024 15:36:19 -0800 Subject: [PATCH 6/6] Editorial: Correct return type of GetDateTimeFormat Some of the DateTimeFormat internal slots may contain null instead of a DateTime Format Record, if no relevant fields were given. That needs to be reflected in the return type of this operation. --- spec/intl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/intl.html b/spec/intl.html index 13ded2a18..bb6e2dc4a 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -820,7 +820,7 @@

_required_: ~date~, ~time~, ~year-month~, ~month-day~, or ~any~, _defaults_: ~date~, ~time~, ~year-month~, ~month-day~, ~zoned-date-time~, or ~all~, _inherit_: ~all~ or ~relevant~, - ): a DateTime Format Record + ): a DateTime Format Record or *null*