diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index a0e32d51d0..ca303e4341 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -1192,6 +1192,7 @@ export function ToTemporalDate(item, options) {
export function InterpretTemporalDateTimeFields(calendar, fields, options) {
let { hour, minute, second, millisecond, microsecond, nanosecond } = ToTemporalTimeRecord(fields);
const overflow = ToTemporalOverflow(options);
+ options.overflow = overflow; // options is always an internal object, so not observable
const date = CalendarDateFromFields(calendar, fields, options);
const year = GetSlot(date, ISO_YEAR);
const month = GetSlot(date, ISO_MONTH);
@@ -1210,14 +1211,16 @@ export function InterpretTemporalDateTimeFields(calendar, fields, options) {
export function ToTemporalDateTime(item, options) {
let year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar;
+ const resolvedOptions = SnapshotOwnProperties(GetOptionsObject(options), null);
+
if (Type(item) === 'Object') {
if (IsTemporalDateTime(item)) return item;
if (IsTemporalZonedDateTime(item)) {
- ToTemporalOverflow(options); // validate and ignore
+ ToTemporalOverflow(resolvedOptions); // validate and ignore
return GetPlainDateTimeFor(GetSlot(item, TIME_ZONE), GetSlot(item, INSTANT), GetSlot(item, CALENDAR));
}
if (IsTemporalDate(item)) {
- ToTemporalOverflow(options); // validate and ignore
+ ToTemporalOverflow(resolvedOptions); // validate and ignore
return CreateTemporalDateTime(
GetSlot(item, ISO_YEAR),
GetSlot(item, ISO_MONTH),
@@ -1239,10 +1242,9 @@ export function ToTemporalDateTime(item, options) {
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } = InterpretTemporalDateTimeFields(
calendar,
fields,
- options
+ resolvedOptions
));
} else {
- ToTemporalOverflow(options); // validate and ignore
let z;
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, z } =
ParseTemporalDateTimeString(RequireString(item)));
@@ -1251,6 +1253,7 @@ export function ToTemporalDateTime(item, options) {
if (!calendar) calendar = 'iso8601';
if (!IsBuiltinCalendar(calendar)) throw new RangeError(`invalid calendar identifier ${calendar}`);
calendar = ASCIILowercase(calendar);
+ ToTemporalOverflow(resolvedOptions); // validate and ignore
}
return CreateTemporalDateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar);
}
@@ -1456,6 +1459,7 @@ export function InterpretISODateTimeOffset(
export function ToTemporalZonedDateTime(item, options) {
let year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, timeZone, offset, calendar;
+ const resolvedOptions = SnapshotOwnProperties(GetOptionsObject(options), null);
let disambiguation, offsetOpt;
let matchMinute = false;
let offsetBehaviour = 'option';
@@ -1479,12 +1483,12 @@ export function ToTemporalZonedDateTime(item, options) {
if (offset === undefined) {
offsetBehaviour = 'wall';
}
- disambiguation = ToTemporalDisambiguation(options);
- offsetOpt = ToTemporalOffset(options, 'reject');
+ disambiguation = ToTemporalDisambiguation(resolvedOptions);
+ offsetOpt = ToTemporalOffset(resolvedOptions, 'reject');
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } = InterpretTemporalDateTimeFields(
calendar,
fields,
- options
+ resolvedOptions
));
} else {
let tzAnnotation, z;
@@ -1513,9 +1517,9 @@ export function ToTemporalZonedDateTime(item, options) {
if (!IsBuiltinCalendar(calendar)) throw new RangeError(`invalid calendar identifier ${calendar}`);
calendar = ASCIILowercase(calendar);
matchMinute = true; // ISO strings may specify offset with less precision
- disambiguation = ToTemporalDisambiguation(options);
- offsetOpt = ToTemporalOffset(options, 'reject');
- ToTemporalOverflow(options); // validate and ignore
+ disambiguation = ToTemporalDisambiguation(resolvedOptions);
+ offsetOpt = ToTemporalOffset(resolvedOptions, 'reject');
+ ToTemporalOverflow(resolvedOptions); // validate and ignore
}
let offsetNs = 0;
if (offsetBehaviour === 'option') offsetNs = ParseDateTimeUTCOffset(offset);
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index 464af91002..e9b05497c1 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -153,7 +153,7 @@ export class PlainDateTime {
}
ES.RejectTemporalLikeObject(temporalDateTimeLike);
- options = ES.GetOptionsObject(options);
+ const resolvedOptions = ES.SnapshotOwnProperties(ES.GetOptionsObject(options), null);
const calendar = GetSlot(this, CALENDAR);
const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']);
let fields = ES.PrepareTemporalFields(this, fieldNames, []);
@@ -168,7 +168,7 @@ export class PlainDateTime {
fields = ES.CalendarMergeFields(calendar, fields, partialDateTime);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } =
- ES.InterpretTemporalDateTimeFields(calendar, fields, options);
+ ES.InterpretTemporalDateTimeFields(calendar, fields, resolvedOptions);
return ES.CreateTemporalDateTime(
year,
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 63d6e9f840..73af21b15d 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -180,7 +180,7 @@ export class ZonedDateTime {
throw new TypeError('invalid zoned-date-time-like');
}
ES.RejectTemporalLikeObject(temporalZonedDateTimeLike);
- options = ES.GetOptionsObject(options);
+ const resolvedOptions = ES.SnapshotOwnProperties(ES.GetOptionsObject(options), null);
const calendar = GetSlot(this, CALENDAR);
const timeZone = GetSlot(this, TIME_ZONE);
@@ -208,11 +208,11 @@ export class ZonedDateTime {
fields = ES.CalendarMergeFields(calendar, fields, partialZonedDateTime);
fields = ES.PrepareTemporalFields(fields, fieldNames, ['offset']);
- const disambiguation = ES.ToTemporalDisambiguation(options);
- const offset = ES.ToTemporalOffset(options, 'prefer');
+ const disambiguation = ES.ToTemporalDisambiguation(resolvedOptions);
+ const offset = ES.ToTemporalOffset(resolvedOptions, 'prefer');
let { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } =
- ES.InterpretTemporalDateTimeFields(calendar, fields, options);
+ ES.InterpretTemporalDateTimeFields(calendar, fields, resolvedOptions);
const newOffsetNs = ES.ParseDateTimeUTCOffset(fields.offset);
const epochNanoseconds = ES.InterpretISODateTimeOffset(
year,
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index 21a4791836..eaa9c80d82 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -398,7 +398,7 @@
Temporal.PlainDateTime.prototype.with ( _temporalDateTimeLike_ [ , _options_
1. If Type(_temporalDateTimeLike_) is not Object, then
1. Throw a *TypeError* exception.
1. Perform ? RejectTemporalLikeObject(_temporalDateTimeLike_).
- 1. Set _options_ to ? GetOptionsObject(_options_).
+ 1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. Let _calendar_ be _dateTime_.[[Calendar]].
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Let _fields_ be ? PrepareTemporalFields(_dateTime_, _fieldNames_, «»).
@@ -412,7 +412,7 @@ Temporal.PlainDateTime.prototype.with ( _temporalDateTimeLike_ [ , _options_
1. Let _partialDateTime_ be ? PrepareTemporalFields(_temporalDateTimeLike_, _fieldNames_, ~partial~).
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDateTime_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
- 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _resolvedOptions_).
1. Assert: IsValidISODate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]]) is *true*.
1. Assert: IsValidTime(_result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]]) is *true*.
1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
@@ -953,8 +953,11 @@ InterpretTemporalDateTimeFields ( _calendar_, _fields_, _options_ )
The abstract operation InterpretTemporalDateTimeFields interprets the date/time fields in the object _fields_ using the given _calendar_, and returns a Record with the fields according to the ISO 8601 calendar.
+ 1. Assert: _options_ is an ordinary extensible Object that is not directly observable from ECMAScript code and for which the value of the [[Prototype]] internal slot is *null* and every property is a configurable data property.
1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ 1. NOTE: The following step is guaranteed to complete normally despite the *"overflow"* property existing, because of the assertion in the first step.
+ 1. Perform ! CreateDataPropertyOrThrow(_options_, *"overflow"*, _overflow_).
1. Let _temporalDate_ be ? CalendarDateFromFields(_calendar_, _fields_, _options_).
1. Let _timeResult_ be ? RegulateTime(_timeResult_.[[Hour]], _timeResult_.[[Minute]], _timeResult_.[[Second]], _timeResult_.[[Millisecond]], _timeResult_.[[Microsecond]], _timeResult_.[[Nanosecond]], _overflow_).
1. Return the Record {
@@ -979,23 +982,23 @@ ToTemporalDateTime ( _item_ [ , _options_ ] )
1. If _options_ is not present, set _options_ to *undefined*.
1. Assert: Type(_options_) is Object or Undefined.
+ 1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. If Type(_item_) is Object, then
1. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then
1. Return _item_.
1. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
- 1. Perform ? ToTemporalOverflow(_options_).
+ 1. Perform ? ToTemporalOverflow(_resolvedOptions_).
1. Let _instant_ be ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
1. Return ? GetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]).
1. If _item_ has an [[InitializedTemporalDate]] internal slot, then
- 1. Perform ? ToTemporalOverflow(_options_).
+ 1. Perform ? ToTemporalOverflow(_resolvedOptions_).
1. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]).
1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_item_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Append *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"nanosecond"*, and *"second"* to _fieldNames_.
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»).
- 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _resolvedOptions_).
1. Else,
- 1. Perform ? ToTemporalOverflow(_options_).
1. If _item_ is not a String, throw a *TypeError* exception.
1. Let _result_ be ? ParseTemporalDateTimeString(_item_).
1. Assert: IsValidISODate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]]) is *true*.
@@ -1004,6 +1007,7 @@ ToTemporalDateTime ( _item_ [ , _options_ ] )
1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. If IsBuiltinCalendar(_calendar_) is *false*, throw a *RangeError* exception.
1. Set _calendar_ to the ASCII-lowercase of _calendar_.
+ 1. Perform ? ToTemporalOverflow(_resolvedOptions_).
1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 54488830ff..45f74faa27 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -584,7 +584,7 @@ Temporal.ZonedDateTime.prototype.with ( _temporalZonedDateTimeLike_ [ , _opt
1. If Type(_temporalZonedDateTimeLike_) is not Object, then
1. Throw a *TypeError* exception.
1. Perform ? RejectTemporalLikeObject(_temporalZonedDateTimeLike_).
- 1. Set _options_ to ? GetOptionsObject(_options_).
+ 1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
1. Let _timeZone_ be _zonedDateTime_.[[TimeZone]].
1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
@@ -604,9 +604,9 @@ Temporal.ZonedDateTime.prototype.with ( _temporalZonedDateTimeLike_ [ , _opt
1. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialZonedDateTime_).
1. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"offset"* »).
1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalDisambiguation reads *"disambiguation"*, ToTemporalOffset reads *"offset"*, and InterpretTemporalDateTimeFields reads *"overflow"*).
- 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
- 1. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
- 1. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_resolvedOptions_).
+ 1. Let _offset_ be ? ToTemporalOffset(_resolvedOptions_, *"prefer"*).
+ 1. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _resolvedOptions_).
1. Let _offsetString_ be ! Get(_fields_, *"offset"*).
1. Assert: Type(_offsetString_) is String.
1. Let _newOffsetNanoseconds_ be ? ParseDateTimeUTCOffset(_offsetString_).
@@ -1158,6 +1158,7 @@
1. If _options_ is not present, set _options_ to *undefined*.
1. Assert: Type(_options_) is Object or Undefined.
+ 1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. Let _offsetBehaviour_ be ~option~.
1. Let _matchBehaviour_ be ~match exactly~.
1. If Type(_item_) is Object, then
@@ -1174,9 +1175,9 @@
1. If _offsetString_ is *undefined*, then
1. Set _offsetBehaviour_ to ~wall~.
1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalDisambiguation reads *"disambiguation"*, ToTemporalOffset reads *"offset"*, and InterpretTemporalDateTimeFields reads *"overflow"*).
- 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
- 1. Let _offsetOption_ be ? ToTemporalOffset(_options_, *"reject"*).
- 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_resolvedOptions_).
+ 1. Let _offsetOption_ be ? ToTemporalOffset(_resolvedOptions_, *"reject"*).
+ 1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _resolvedOptions_).
1. Else,
1. If _item_ is not a String, throw a *TypeError* exception.
1. Let _result_ be ? ParseTemporalZonedDateTimeString(_item_).
@@ -1193,9 +1194,9 @@
1. If IsBuiltinCalendar(_calendar_) is *false*, throw a *RangeError* exception.
1. Set _calendar_ to the ASCII-lowercase of _calendar_.
1. Set _matchBehaviour_ to ~match minutes~.
- 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
- 1. Let _offsetOption_ be ? ToTemporalOffset(_options_, *"reject"*).
- 1. Perform ? ToTemporalOverflow(_options_).
+ 1. Let _disambiguation_ be ? ToTemporalDisambiguation(_resolvedOptions_).
+ 1. Let _offsetOption_ be ? ToTemporalOffset(_resolvedOptions_, *"reject"*).
+ 1. Perform ? ToTemporalOverflow(_resolvedOptions_).
1. Let _offsetNanoseconds_ be 0.
1. If _offsetBehaviour_ is ~option~, then
1. Set _offsetNanoseconds_ to ? ParseDateTimeUTCOffset(_offsetString_).