summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with')
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js65
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-array-iteration.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-observable-calls.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-timezone-no-observable-calls.js37
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-options.js35
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/constructor-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js61
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js52
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/duplicate-calendar-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/getpossibleinstantsfor-called-with-iso8601-calendar.js61
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/minimum-instant-with-one-hour-offset.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-invalid-string.js35
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-object.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/order-of-operations.js177
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/proto-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js59
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js39
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time-with-offset.js42
-rw-r--r--js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time.js37
49 files changed, 1639 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js
new file mode 100644
index 0000000000..e7935824fd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/balance-negative-time-units.js
@@ -0,0 +1,65 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Negative time fields are balanced upwards
+info: |
+ sec-temporal-balancetime steps 3–14:
+ 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000).
+ 4. Set _nanosecond_ to _nanosecond_ modulo 1000.
+ 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000).
+ 6. Set _microsecond_ to _microsecond_ modulo 1000.
+ 7. Set _second_ to _second_ + floor(_millisecond_ / 1000).
+ 8. Set _millisecond_ to _millisecond_ modulo 1000.
+ 9. Set _minute_ to _minute_ + floor(_second_ / 60).
+ 10. Set _second_ to _second_ modulo 60.
+ 11. Set _hour_ to _hour_ + floor(_minute_ / 60).
+ 12. Set _minute_ to _minute_ modulo 60.
+ 13. Let _days_ be floor(_hour_ / 24).
+ 14. Set _hour_ to _hour_ modulo 24.
+ sec-temporal-addtime step 8:
+ 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_).
+ sec-temporal-adddatetime step 1:
+ 1. Let _timeResult_ be ? AddTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
+ sec-temporal-builtintimezonegetinstantfor step 13.a:
+ a. Let _earlier_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], 0, 0, 0, 0, 0, 0, 0, 0, 0, −_nanoseconds_, *"constrain"*).
+ sec-temporal-interpretisodatetimeoffset steps 4–10:
+ 4. If _offsetNanoseconds_ is *null*, or _offset_ is *"ignore"*, then
+ a. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_).
+ ...
+ ...
+ 6. Assert: _offset_ is *"prefer"* or *"reject"*.
+ 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_).
+ ...
+ 9. If _offset_ is *"reject"*, throw a *RangeError* exception.
+ 10. Let _instant_ be ? DisambiguatePossibleInstants(_possibleInstants_, _timeZone_, _dateTime_, _disambiguation_).
+ sec-temporal.zoneddatetime.prototype.with step 26:
+ 26. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_dateTimeResult_.[[Year]], _dateTimeResult_.[[Month]], _dateTimeResult_.[[Day]], _dateTimeResult_.[[Hour]], _dateTimeResult_.[[Minute]], _dateTimeResult_.[[Second]], _dateTimeResult_.[[Millisecond]], _dateTimeResult_.[[Microsecond]], _dateTimeResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const shiftInstant = new Temporal.Instant(3661_001_001_001n);
+const tz1 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2);
+const datetime1 = new Temporal.ZonedDateTime(3661_001_001_000n, tz1);
+
+// This code path is encountered if offset is `ignore` or `prefer`,
+// disambiguation is `earlier` and the shift is a spring-forward change
+datetime1.with({ nanosecond: 1 }, { offset: "ignore", disambiguation: "earlier" });
+
+const expected = [
+ "1970-01-01T01:01:01.001001001",
+ "1970-01-01T01:01:01.001000999",
+];
+assert.compareArray(tz1.getPossibleInstantsForCalledWith, expected);
+
+const tz2 = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2);
+const datetime2 = new Temporal.ZonedDateTime(3661_001_001_000n, tz2);
+
+datetime2.with({ nanosecond: 1 }, { offset: "prefer", disambiguation: "earlier" });
+
+assert.compareArray(tz2.getPossibleInstantsForCalledWith, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/branding.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/branding.js
new file mode 100644
index 0000000000..089d357535
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/branding.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const with_ = Temporal.ZonedDateTime.prototype.with;
+
+assert.sameValue(typeof with_, "function");
+
+const args = [{ year: 2022 }];
+
+assert.throws(TypeError, () => with_.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => with_.apply(null, args), "null");
+assert.throws(TypeError, () => with_.apply(true, args), "true");
+assert.throws(TypeError, () => with_.apply("", args), "empty string");
+assert.throws(TypeError, () => with_.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => with_.apply(1, args), "1");
+assert.throws(TypeError, () => with_.apply({}, args), "plain object");
+assert.throws(TypeError, () => with_.apply(Temporal.ZonedDateTime, args), "Temporal.ZonedDateTime");
+assert.throws(TypeError, () => with_.apply(Temporal.ZonedDateTime.prototype, args), "Temporal.ZonedDateTime.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/browser.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..29b963ecf8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-array-iteration.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable array iteration when getting the calendar fields.
+features: [Temporal]
+---*/
+
+const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator];
+Array.prototype[Symbol.iterator] = function arrayIterator() {
+ throw new Test262Error("Array should not be iterated");
+}
+
+const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "iso8601");
+instance.with({ day: 5 });
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..0d3f1edc2f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-calendar-no-observable-calls.js
@@ -0,0 +1,46 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const fieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "fields");
+Object.defineProperty(Temporal.Calendar.prototype, "fields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("fields should not be looked up");
+ },
+});
+const mergeFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "mergeFields");
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("mergeFields should not be looked up");
+ },
+});
+const dateFromFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "dateFromFields");
+Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("dateFromFields should not be looked up");
+ },
+});
+
+const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "iso8601");
+instance.with({ year: 2001 });
+
+Object.defineProperty(Temporal.Calendar.prototype, "fields", fieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", mergeFieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", dateFromFieldsOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-timezone-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-timezone-no-observable-calls.js
new file mode 100644
index 0000000000..d40d49f7fb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin-timezone-no-observable-calls.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Calling the method on an instance constructed with a builtin time zone causes
+ no observable lookups or calls to time zone methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const getOffsetNanosecondsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor");
+Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("getOffsetNanosecondsFor should not be looked up");
+ },
+});
+const getPossibleInstantsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getPossibleInstantsFor");
+Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("getPossibleInstantsFor should not be looked up");
+ },
+});
+
+const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", "iso8601");
+instance.with({ year: 2001 });
+
+Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", getOffsetNanosecondsForOriginal);
+Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", getPossibleInstantsForOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js
new file mode 100644
index 0000000000..c18d00211d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/builtin.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Tests that Temporal.ZonedDateTime.prototype.with
+ meets the requirements for built-in objects defined by the
+ introduction of chapter 17 of the ECMAScript Language Specification.
+info: |
+ Built-in functions that are not constructors do not have a "prototype" property unless
+ otherwise specified in the description of a particular function.
+
+ Unless specified otherwise, a built-in object that is callable as a function is a built-in
+ function object with the characteristics described in 10.3. Unless specified otherwise, the
+ [[Extensible]] internal slot of a built-in object initially has the value true.
+
+ Unless otherwise specified every built-in function and every built-in constructor has the
+ Function prototype object [...] as the value of its [[Prototype]] internal slot.
+features: [Temporal]
+---*/
+
+assert.sameValue(Object.isExtensible(Temporal.ZonedDateTime.prototype.with),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.ZonedDateTime.prototype.with),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.ZonedDateTime.prototype.with),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.ZonedDateTime.prototype.with.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js
new file mode 100644
index 0000000000..7993c23c19
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fields-iterable.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.zoneddatetime.prototype.with step 9:
+ 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
+ sec-temporal-calendarfields step 4:
+ 4. Let _result_ be ? IterableToList(_fieldsArray_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "day",
+ "month",
+ "monthCode",
+ "year",
+];
+
+const calendar = TemporalHelpers.calendarFieldsIterable();
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
+datetime.with({ year: 2005 });
+
+assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once");
+assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args");
+assert(calendar.iteratorExhausted[0], "iterated through the whole iterable");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..35d0c27f9f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Calendar.dateFromFields method is called with a null-prototype fields object
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
+const instance = new Temporal.ZonedDateTime(0n, "UTC", calendar);
+instance.with({ day: 24 });
+assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js
new file mode 100644
index 0000000000..7f1e187cbf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-merge-fields-returns-primitive.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ with() should throw a TypeError if mergeFields() returns a primitive,
+ without passing the value on to any other calendar methods
+includes: [compareArray.js, temporalHelpers.js]
+features: [BigInt, Symbol, Temporal]
+---*/
+
+[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => {
+ const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive);
+ const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
+ assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws");
+ assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..6a75d5ce22
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Calendar.mergeFields method is called with null-prototype fields objects
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckMergeFieldsPrototypePollution();
+const instance = new Temporal.ZonedDateTime(0n, "UTC", calendar);
+instance.with({ day: 24 });
+assert.sameValue(calendar.mergeFieldsCallCount, 1, "mergeFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-options.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-options.js
new file mode 100644
index 0000000000..2daa8e28ec
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/calendar-options.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ The options argument is copied and the copy is passed to
+ Calendar#dateFromFields.
+features: [Temporal]
+---*/
+
+const options = {
+ extra: "property",
+};
+let calledDateFromFields = 0;
+class Calendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+ dateFromFields(fields, optionsArg) {
+ ++calledDateFromFields;
+ assert.notSameValue(optionsArg, options, "should pass copied options object");
+ assert.sameValue(optionsArg.extra, "property", "should copy all properties from options object");
+ assert.sameValue(Object.getPrototypeOf(optionsArg), null, "Copy has null prototype");
+ return super.dateFromFields(fields, optionsArg);
+ }
+};
+const calendar = new Calendar();
+const datetime = new Temporal.ZonedDateTime(0n, "UTC", calendar);
+const result = datetime.with({ year: 1971 }, options);
+assert.sameValue(result.epochNanoseconds, 365n * 86400_000_000_000n, "year changed from 1970 to 1971")
+assert.sameValue(calledDateFromFields, 1, "should have called overridden dateFromFields once");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..640cd8d689
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/constructor-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']);
+const zoneddatetime = new Temporal.ZonedDateTime(1682892000000000000n, 'Europe/Madrid', calendar);
+
+assert.throws(RangeError, () => zoneddatetime.with({hour: 12}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js
new file mode 100644
index 0000000000..dc159e00f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copies-merge-fields-object.js
@@ -0,0 +1,61 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: The object returned from mergeFields() is copied before being passed to dateFromFields().
+info: |
+ sec-temporal.plaindatetime.prototype.with steps 18–19 and 23:
+ 18. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialDate_).
+ 19. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"timeZone"* »).
+ 23. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ sec-temporal-interprettemporaldatetimefields step 2:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "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 offset",
+ "get offset.toString",
+ "call offset.toString",
+ "get second",
+ "get second.valueOf",
+ "call second.valueOf",
+ "get year",
+ "get year.valueOf",
+ "call year.valueOf",
+];
+
+const calendar = TemporalHelpers.calendarMergeFieldsGetters();
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
+datetime.with({ year: 2022 });
+
+assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js
new file mode 100644
index 0000000000..6afaf10645
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/copy-properties-not-undefined.js
@@ -0,0 +1,52 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: PreparePartialTemporalFields copies only defined properties of source object
+info: |
+ 4. For each value _property_ of _fieldNames_, do
+ a. Let _value_ be ? Get(_fields_, _property_).
+ b. If _value_ is not *undefined*, then
+ ...
+ iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_).
+features: [Temporal]
+---*/
+
+const d1 = new Temporal.ZonedDateTime(1_000_000_000_000_000_789n, "UTC");
+
+const d2 = d1.with({ day: 1, hour: 10, year: undefined });
+
+assert.sameValue(d2.year, 2001,
+ "only the properties that are present and defined in the plain object are copied (year value)"
+);
+
+assert.sameValue(d2.month, 9,
+ "only the properties that are present and defined in the plain object are copied (month value)"
+);
+
+assert.sameValue(d2.day, 1,
+ "only the properties that are present and defined in the plain object are copied (day value)"
+);
+
+assert.sameValue(d2.hour, 10,
+ "only the properties that are present and defined in the plain object are copied (hour value)"
+);
+assert.sameValue(d2.minute, 46,
+ "only the properties that are present and defined in the plain object are copied (minute value)"
+);
+assert.sameValue(d2.second, 40,
+ "only the properties that are present and defined in the plain object are copied (second value)"
+);
+assert.sameValue(d2.millisecond, 0,
+ "only the properties that are present and defined in the plain object are copied (millisecond value)"
+);
+assert.sameValue(d2.microsecond, 0,
+ "only the properties that are present and defined in the plain object are copied (microsecond value)"
+);
+assert.sameValue(d2.nanosecond, 789,
+ "only the properties that are present and defined in the plain object are copied (nanosecond value)"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..8cf415e441
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-invalid-string.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.with
+description: RangeError thrown when disambiguation option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.with({ hour: 2 }, { disambiguation: "other string" }));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js
new file mode 100644
index 0000000000..e81165eeb7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-undefined.js
@@ -0,0 +1,34 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for disambiguation option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardDatetime = new Temporal.ZonedDateTime(954702001_000_000_000n, timeZone);
+const fallBackDatetime = new Temporal.ZonedDateTime(972849601_000_000_000n, timeZone);
+const offset = "ignore";
+
+[
+ [springForwardDatetime, { hour: 2, minute: 30 }, 954671401_000_000_000n],
+ [fallBackDatetime, { hour: 1, minute: 30 }, 972808201_000_000_000n],
+].forEach(([datetime, fields, expected]) => {
+ const explicit = datetime.with(fields, { offset, disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const implicit = datetime.with(fields, { offset });
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..90358a2752
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/disambiguation-wrong-type.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Type conversions for disambiguation option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => datetime.with({ hour: 2 }, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..bcf2046f1c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/duplicate-calendar-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+for (const extra_fields of [['foo', 'foo'], ['monthCode'], ['day'], ['hour'], ['microsecond'], ['millisecond'], ['minute'], ['month'], ['nanosecond'], ['second'], ['year'], ['offset']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const zoneddatetime = new Temporal.ZonedDateTime(1682892000000000000n, 'Europe/Madrid', calendar);
+
+ assert.throws(RangeError, () => zoneddatetime.with({hour: 12}));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/getpossibleinstantsfor-called-with-iso8601-calendar.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/getpossibleinstantsfor-called-with-iso8601-calendar.js
new file mode 100644
index 0000000000..67a199f72f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/getpossibleinstantsfor-called-with-iso8601-calendar.js
@@ -0,0 +1,61 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Time zone's getPossibleInstantsFor is called with a PlainDateTime with the
+ built-in ISO 8601 calendar
+features: [Temporal]
+info: |
+ DisambiguatePossibleInstants:
+ 2. Let _n_ be _possibleInstants_'s length.
+ ...
+ 5. Assert: _n_ = 0.
+ ...
+ 19. If _disambiguation_ is *"earlier"*, then
+ ...
+ c. Let _earlierDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
+ d. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _earlierDateTime_).
+ ...
+ 20. Assert: _disambiguation_ is *"compatible"* or *"later"*.
+ ...
+ 23. Let _laterDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
+ 24. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _laterDateTime_).
+---*/
+
+class SkippedDateTime extends Temporal.TimeZone {
+ constructor() {
+ super("UTC");
+ this.calls = 0;
+ }
+
+ getPossibleInstantsFor(dateTime) {
+ // Calls occur in pairs. For the first one return no possible instants so
+ // that DisambiguatePossibleInstants will call it again
+ if (this.calls++ % 2 == 0) {
+ return [];
+ }
+
+ assert.sameValue(
+ dateTime.getISOFields().calendar,
+ "iso8601",
+ "getPossibleInstantsFor called with dateTime with built-in ISO 8601 calendar"
+ );
+ return super.getPossibleInstantsFor(dateTime);
+ }
+}
+
+const nonBuiltinISOCalendar = new Temporal.Calendar("iso8601");
+
+for (const disambiguation of ["earlier", "later", "compatible"]) {
+ const timeZone = new SkippedDateTime();
+ const instance = new Temporal.ZonedDateTime(0n, timeZone, nonBuiltinISOCalendar);
+
+ instance.with({ day: 1 }, { disambiguation });
+
+ assert.sameValue(timeZone.calls, 2, "getPossibleInstantsFor should have been called 2 times");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..2dc6beff59
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/infinity-throws-rangeerror.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Throws if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.zoneddatetime.prototype.with
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => {
+ ["constrain", "reject"].forEach((overflow) => {
+ assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
+ assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow }));
+ assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value");
+ });
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js
new file mode 100644
index 0000000000..89ac918633
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Temporal.ZonedDateTime.prototype.with.length is 1
+info: |
+ Every built-in function object, including constructors, has a "length" property whose value is
+ an integer. Unless otherwise specified, this value is equal to the largest number of named
+ arguments shown in the subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form
+ «...name») are not included in the default argument count.
+
+ Unless otherwise specified, the "length" property of a built-in function object has the
+ attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.ZonedDateTime.prototype.with, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/minimum-instant-with-one-hour-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/minimum-instant-with-one-hour-offset.js
new file mode 100644
index 0000000000..09ebb9c90b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/minimum-instant-with-one-hour-offset.js
@@ -0,0 +1,33 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Throws a RangeError when ZonedDateTime at minimum instant and an explicit +1h offset.
+info: |
+ Temporal.ZonedDateTime.prototype.with ( temporalZonedDateTimeLike [ , options ] )
+ ...
+ 21. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[Year]],
+ dateTimeResult.[[Month]], dateTimeResult.[[Day]], dateTimeResult.[[Hour]],
+ dateTimeResult.[[Minute]], dateTimeResult.[[Second]], dateTimeResult.[[Millisecond]],
+ dateTimeResult.[[Microsecond]], dateTimeResult.[[Nanosecond]], option, offsetNanoseconds,
+ timeZone, disambiguation, offset, match exactly).
+ ...
+features: [Temporal]
+---*/
+
+let zdt = new Temporal.ZonedDateTime(-86_40000_00000_00000_00000n, "UTC");
+
+let temporalZonedDateTimeLike = {
+ offset: "+01",
+};
+
+let options = {
+ offset: "use",
+};
+
+assert.throws(RangeError, () => zdt.with(temporalZonedDateTimeLike, options));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js
new file mode 100644
index 0000000000..cfff0818fd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/name.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Temporal.ZonedDateTime.prototype.with.name is "with".
+info: |
+ Every built-in function object, including constructors, that is not identified as an anonymous
+ function has a "name" property whose value is a String. Unless otherwise specified, this value
+ is the name that is given to the function in this specification.
+
+ Unless otherwise specified, the "name" property of a built-in function object, if it exists,
+ has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.ZonedDateTime.prototype.with, "name", {
+ value: "with",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js
new file mode 100644
index 0000000000..6487ca2e44
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/not-a-constructor.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Temporal.ZonedDateTime.prototype.with does not implement [[Construct]], is not new-able
+info: |
+ Built-in function objects that are not identified as constructors do not implement the
+ [[Construct]] internal method unless otherwise specified in the description of a particular
+ function.
+includes: [isConstructor.js]
+features: [Reflect.construct, Temporal]
+---*/
+
+assert.throws(TypeError, () => {
+ new Temporal.ZonedDateTime.prototype.with();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.ZonedDateTime.prototype.with), false,
+ "isConstructor(Temporal.ZonedDateTime.prototype.with)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js
new file mode 100644
index 0000000000..d099f8857a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-invalid-string.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.with
+description: RangeError thrown when offset option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.with({ hour: 2 }, { offset: "other string" }));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-invalid-string.js
new file mode 100644
index 0000000000..cc48282502
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-property-invalid-string.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Property bag with offset property is rejected if offset is in the wrong format
+features: [Temporal]
+---*/
+
+const timeZone = new Temporal.TimeZone("UTC");
+const instance = new Temporal.ZonedDateTime(0n, timeZone);
+
+const offsetOptions = ['use', 'prefer', 'ignore', 'reject'];
+
+const badOffsets = [
+ "00:00", // missing sign
+ "+0", // too short
+ "-000:00", // too long
+ 0, // must be a string
+ null, // must be a string
+ true, // must be a string
+ 1000n, // must be a string
+];
+offsetOptions.forEach((offsetOption) => {
+ badOffsets.forEach((offset) => {
+ assert.throws(
+ typeof(offset) === 'string' ? RangeError : TypeError,
+ () => instance.with({ offset }, { offset: offsetOption }),
+ `"${offset} is not a valid offset string (with ${offsetOption} offset option)`,
+ );
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js
new file mode 100644
index 0000000000..f48b9c750e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-undefined.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for offset option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+features: [Temporal]
+---*/
+
+const timeZone = new Temporal.TimeZone("-03:30");
+
+const datetime = new Temporal.ZonedDateTime(1572757201_000_000_000n, timeZone);
+const explicit = datetime.with({ minute: 31 }, { offset: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer");
+const implicit = datetime.with({ minute: 31 }, {});
+assert.sameValue(implicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js
new file mode 100644
index 0000000000..af450155ca
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/offset-wrong-type.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Type conversions for offset option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("offset", "prefer",
+ (offset) => datetime.with({ hour: 2 }, { offset }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-object.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-object.js
new file mode 100644
index 0000000000..9674f868a4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-object.js
@@ -0,0 +1,25 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Empty or a function object may be used as options
+features: [Temporal]
+---*/
+
+const instance = new Temporal.ZonedDateTime(0n, "UTC");
+
+const result1 = instance.with({ day: 5 }, {});
+assert.sameValue(
+ result1.epochNanoseconds, 345600000000000n, "UTC",
+ "options may be an empty plain object"
+);
+
+const result2 = instance.with({ day: 5 }, () => {});
+assert.sameValue(
+ result2.epochNanoseconds, 345600000000000n, "UTC",
+ "options may be a function object"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js
new file mode 100644
index 0000000000..e648410e0e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-undefined.js
@@ -0,0 +1,22 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Verify that undefined options are handled correctly.
+features: [BigInt, Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(949494896_987_654_321n, "UTC");
+const fields = { day: 31 };
+
+const explicit = datetime.with(fields, undefined);
+assert.sameValue(explicit.month, 2, "default overflow is constrain");
+assert.sameValue(explicit.day, 29, "default overflow is constrain");
+
+const implicit = datetime.with(fields);
+assert.sameValue(implicit.month, 2, "default overflow is constrain");
+assert.sameValue(implicit.day, 29, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js
new file mode 100644
index 0000000000..94ea786d19
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: TypeError thrown when options argument is a primitive
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const badOptions = [
+ null,
+ true,
+ "some string",
+ Symbol(),
+ 1,
+ 2n,
+];
+
+const instance = new Temporal.ZonedDateTime(0n, "UTC");
+for (const value of badOptions) {
+ assert.throws(TypeError, () => instance.with({ day: 5 }, value),
+ `TypeError on wrong options type ${typeof value}`);
+};
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/order-of-operations.js
new file mode 100644
index 0000000000..18387ceb9a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/order-of-operations.js
@@ -0,0 +1,177 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Properties on objects passed to with() are accessed in the correct order
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ // RejectObjectWithCalendarOrTimeZone
+ "get fields.calendar",
+ "get fields.timeZone",
+ // CopyDataProperties
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+ "getOwnPropertyDescriptor options.disambiguation",
+ "get options.disambiguation",
+ "getOwnPropertyDescriptor options.offset",
+ "get options.offset",
+ "getOwnPropertyDescriptor options.extra",
+ "get options.extra",
+ // lookup
+ "get this.calendar.dateFromFields",
+ "get this.calendar.fields",
+ "get this.calendar.mergeFields",
+ // lookup
+ "get this.timeZone.getOffsetNanosecondsFor",
+ "get this.timeZone.getPossibleInstantsFor",
+ // GetOffsetNanosecondsFor on receiver
+ "call this.timeZone.getOffsetNanosecondsFor",
+ // CalendarFields
+ "call this.calendar.fields",
+ // PrepareTemporalFields on receiver
+ "get this.calendar.day",
+ "call this.calendar.day",
+ "get this.calendar.month",
+ "call this.calendar.month",
+ "get this.calendar.monthCode",
+ "call this.calendar.monthCode",
+ "get this.calendar.year",
+ "call this.calendar.year",
+ // PrepareTemporalFields on argument
+ "get fields.day",
+ "get fields.day.valueOf",
+ "call fields.day.valueOf",
+ "get fields.hour",
+ "get fields.hour.valueOf",
+ "call fields.hour.valueOf",
+ "get fields.microsecond",
+ "get fields.microsecond.valueOf",
+ "call fields.microsecond.valueOf",
+ "get fields.millisecond",
+ "get fields.millisecond.valueOf",
+ "call fields.millisecond.valueOf",
+ "get fields.minute",
+ "get fields.minute.valueOf",
+ "call fields.minute.valueOf",
+ "get fields.month",
+ "get fields.month.valueOf",
+ "call fields.month.valueOf",
+ "get fields.monthCode",
+ "get fields.monthCode.toString",
+ "call fields.monthCode.toString",
+ "get fields.nanosecond",
+ "get fields.nanosecond.valueOf",
+ "call fields.nanosecond.valueOf",
+ "get fields.offset",
+ "get fields.offset.toString",
+ "call fields.offset.toString",
+ "get fields.second",
+ "get fields.second.valueOf",
+ "call fields.second.valueOf",
+ "get fields.year",
+ "get fields.year.valueOf",
+ "call fields.year.valueOf",
+ // CalendarMergeFields
+ "call this.calendar.mergeFields",
+ // InterpretTemporalDateTimeFields
+ "get options.disambiguation.toString",
+ "call options.disambiguation.toString",
+ "get options.offset.toString",
+ "call options.offset.toString",
+ "get options.overflow.toString",
+ "call options.overflow.toString",
+ "call this.calendar.dateFromFields",
+ // InterpretISODateTimeOffset
+ "call this.timeZone.getPossibleInstantsFor",
+ "call this.timeZone.getOffsetNanosecondsFor",
+];
+const actual = [];
+
+const timeZone = TemporalHelpers.timeZoneObserver(actual, "this.timeZone");
+const calendar = TemporalHelpers.calendarObserver(actual, "this.calendar");
+const instance = new Temporal.ZonedDateTime(0n, timeZone, calendar);
+// clear observable operations that occurred during the constructor call
+actual.splice(0);
+
+const fields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 1.7,
+ month: 1.7,
+ monthCode: "M01",
+ day: 1.7,
+ hour: 1.7,
+ minute: 1.7,
+ second: 1.7,
+ millisecond: 1.7,
+ microsecond: 1.7,
+ nanosecond: 1.7,
+ offset: "+00:00",
+}, "fields");
+
+const options = TemporalHelpers.propertyBagObserver(actual, {
+ overflow: "constrain",
+ disambiguation: "compatible",
+ offset: "prefer",
+ extra: "property",
+}, "options");
+
+instance.with(fields, options);
+assert.compareArray(actual, expected, "order of operations");
+actual.splice(0); // clear
+
+const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const dstTimeZoneObserver = TemporalHelpers.timeZoneObserver(actual, "this.timeZone", {
+ getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor,
+ getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor,
+});
+
+const dstInstance = new Temporal.ZonedDateTime(37800_000_000_000n /* 1970-01-01T02:30-08:00 */, dstTimeZoneObserver, calendar);
+actual.splice(0); // clear calls that happened in constructor
+
+const fallBackFields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 2000,
+ month: 10,
+ monthCode: "M10",
+ day: 29,
+ hour: 1,
+ minute: 30,
+ second: 0,
+ millisecond: 0,
+ microsecond: 0,
+ nanosecond: 0,
+ offset: "+00:00", // ignored
+}, "fields");
+dstInstance.with(fallBackFields, options);
+assert.compareArray(actual, expected.concat([
+ // extra call in InterpretISODateTimeOffset
+ "call this.timeZone.getOffsetNanosecondsFor",
+]), "order of operations at repeated wall-clock time");
+actual.splice(0); // clear
+
+const springForwardFields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 2000,
+ month: 4,
+ monthCode: "M04",
+ day: 2,
+ hour: 2,
+ minute: 30,
+ second: 0,
+ millisecond: 0,
+ microsecond: 0,
+ nanosecond: 0,
+ offset: "+00:00", // ignored
+}, "fields");
+dstInstance.with(springForwardFields, options);
+assert.compareArray(actual, expected.concat([
+ // DisambiguatePossibleInstants
+ "call this.timeZone.getOffsetNanosecondsFor",
+ "call this.timeZone.getPossibleInstantsFor",
+]), "order of operations at skipped wall-clock time");
+actual.splice(0); // clear
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..8e2be9a65f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: RangeError thrown when overflow option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"];
+for (const overflow of badOverflows) {
+ assert.throws(
+ RangeError,
+ () => datetime.with({ minute: 45 }, { overflow }),
+ `invalid overflow ("${overflow}")`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..17e7dd007f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-undefined.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for overflow option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const explicit = datetime.with({ second: 67 }, { overflow: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain");
+const implicit = datetime.with({ second: 67 }, {});
+assert.sameValue(implicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..1ce7632251
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,48 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Type conversions for overflow option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: null }), "null");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: true }), "true");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: false }), "false");
+assert.throws(TypeError, () => datetime.with({ second: 41 }, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: 2 }), "number");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: {} }), "plain object");
+
+// toString property should only be read and converted to a string once, because
+// a copied object with the resulting string on it is passed to
+// Calendar.dateFromFields().
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = datetime.with({ second: 41 }, { overflow: observer });
+assert.sameValue(result.epochNanoseconds, 1_000_000_001_987_654_321n, "object with toString");
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js
new file mode 100644
index 0000000000..510a4ed819
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/prop-desc.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: The "with" property of Temporal.ZonedDateTime.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.ZonedDateTime.prototype.with,
+ "function",
+ "`typeof ZonedDateTime.prototype.with` is `function`"
+);
+
+verifyProperty(Temporal.ZonedDateTime.prototype, "with", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..e7eca2b136
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/proto-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']);
+const zoneddatetime = new Temporal.ZonedDateTime(1682892000000000000n, 'Europe/Madrid', calendar);
+
+assert.throws(RangeError, () => zoneddatetime.with({hour: 12}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js
new file mode 100644
index 0000000000..0977701e40
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/read-time-fields-before-datefromfields.js
@@ -0,0 +1,29 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: The time fields are read from the object before being passed to dateFromFields().
+info: |
+ sec-temporal.zoneddatetime.prototype.with step 23:
+ 23. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ sec-temporal-interprettemporaldatetimefields steps 1–2:
+ 1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_).
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarMakeInfinityTime();
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar);
+const newDatetime = datetime.with({ year: 2022 });
+
+assert.sameValue(newDatetime.hour, 1, "hour value");
+assert.sameValue(newDatetime.minute, 46, "minute value");
+assert.sameValue(newDatetime.second, 40, "second value");
+assert.sameValue(newDatetime.millisecond, 987, "millisecond value");
+assert.sameValue(newDatetime.microsecond, 654, "microsecond value");
+assert.sameValue(newDatetime.nanosecond, 321, "nanosecond value");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js
new file mode 100644
index 0000000000..c47d2634eb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/receiver-offset-broken.js
@@ -0,0 +1,59 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.with
+description: >
+ TypeError thrown when the offset field of the argument or the object returned
+ from mergeFields is broken
+info: |
+ 7. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
+ 8. Append *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"nanosecond"*, *"offset"*, and *"second"* to _fieldNames_.
+ 9. Let _fields_ be ? PrepareTemporalFields(_zonedDateTime_, _fieldNames_, « *"offset"* »).
+ 10. Let _partialZonedDateTime_ be ? PrepareTemporalFields(_temporalZonedDateTimeLike_, _fieldNames_, ~partial~).
+ 11. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialZonedDateTime_).
+ 12. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, « *"offset"* »).
+features: [Temporal]
+---*/
+
+class ObservedCalendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ this.resetCalls();
+ }
+
+ toString() {
+ return "observed-calendar";
+ }
+
+ mergeFields(original, additional) {
+ this.mergeFieldsCalled++;
+ const result = super.mergeFields(original, additional);
+ result.offset = Symbol("can't convert to string");
+ return result;
+ }
+
+ resetCalls() {
+ this.mergeFieldsCalled = 0;
+ }
+}
+
+const calendar = new ObservedCalendar();
+const dateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar);
+
+// Test throw in step 10
+
+assert.throws(TypeError, () => dateTime.with({ offset: Symbol("can't convert to string") }), "conversion failure on ZonedDateTime-like");
+assert.sameValue(calendar.mergeFieldsCalled, 0, "calendar.mergeFields should not be called");
+
+calendar.resetCalls();
+
+// Test throw in step 12 (before sabotaging the ZonedDateTime instance)
+
+assert.throws(TypeError, () => dateTime.with({ year: 2002 }), "conversion failure on sabotaged return value from mergeFields");
+assert.sameValue(calendar.mergeFieldsCalled, 1, "calendar.mergeFields was called once");
+
+calendar.resetCalls();
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js
new file mode 100644
index 0000000000..7435848f8d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/subclassing-ignored.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Objects of a subclass are never created as return values.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkSubclassingIgnored(
+ Temporal.ZonedDateTime,
+ [10n, "UTC"],
+ "with",
+ [{ year: 2000 }],
+ (result) => {
+ assert.sameValue(result.epochNanoseconds, 946684800_000_000_010n, "epochNanoseconds result");
+ assert.sameValue(result.year, 2000, "year result");
+ assert.sameValue(result.month, 1, "month result");
+ assert.sameValue(result.day, 1, "day result");
+ assert.sameValue(result.hour, 0, "hour result");
+ assert.sameValue(result.minute, 0, "minute result");
+ assert.sameValue(result.second, 0, "second result");
+ assert.sameValue(result.millisecond, 0, "millisecond result");
+ assert.sameValue(result.microsecond, 0, "microsecond result");
+ assert.sameValue(result.nanosecond, 10, "nanosecond result");
+ },
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js
new file mode 100644
index 0000000000..abcf246b03
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-non-integer.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => {
+ const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
+ assert.throws(RangeError, () => datetime.with({ day: 27 }));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js
new file mode 100644
index 0000000000..49db5085a5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-not-callable.js
@@ -0,0 +1,39 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable
+features: [BigInt, Symbol, Temporal, arrow-function]
+---*/
+
+[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => {
+ const timeZone = new Temporal.TimeZone("UTC");
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
+ timeZone.getOffsetNanosecondsFor = notCallable;
+ assert.throws(
+ TypeError,
+ () => datetime.with({ day: 27 }, { offset: "prefer" }),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no disambiguation case)`
+ );
+
+ const badTimeZone = {
+ id: "Etc/Bad",
+ getPossibleInstantsFor() { return []; },
+ getOffsetNanosecondsFor: notCallable,
+ };
+ const badDateTime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, badTimeZone);
+ assert.throws(
+ TypeError,
+ () => badDateTime.with({ day: 27 }, { offset: "ignore" }),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=ignore and no possible instants case)`
+ );
+ assert.throws(
+ TypeError,
+ () => badDateTime.with({ day: 27 }, { offset: "prefer" }),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError (in offset=prefer and no possible instants case)`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js
new file mode 100644
index 0000000000..cec9c2b6e5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-out-of-range.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: RangeError thrown if time zone reports an offset that is out of range
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => {
+ const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
+ assert.throws(RangeError, () => datetime.with({ day: 27 }));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js
new file mode 100644
index 0000000000..7d1d89673b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getoffsetnanosecondsfor-wrong-type.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: TypeError thrown if time zone reports an offset that is not a Number
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+[
+ undefined,
+ null,
+ true,
+ "+01:00",
+ Symbol(),
+ 3600_000_000_000n,
+ {},
+ { valueOf() { return 3600_000_000_000; } },
+].forEach((wrongOffset) => {
+ const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
+ assert.throws(TypeError, () => datetime.with({ day: 27 }));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js
new file mode 100644
index 0000000000..c24bad7373
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call
+info: |
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_dateTimeResult_.[[Year]], [...], _dateTimeResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_).
+ sec-temporal-interpretisodatetimeoffset step 7:
+ 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_).
+ sec-temporal-getpossibleinstantsfor step 2:
+ 2. Let _list_ be ? IterableToList(_possibleInstants_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "2005-09-09T01:46:40",
+];
+
+TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => {
+ const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone);
+ datetime.with({ year: 2005 });
+}, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time-with-offset.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time-with-offset.js
new file mode 100644
index 0000000000..f4fbeff05b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time-with-offset.js
@@ -0,0 +1,42 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Throws a RangeError for the minimum date/value with UTC offset and an explicit offset.
+info: |
+ Temporal.ZonedDateTime.prototype.with ( temporalZonedDateTimeLike [ , options ] )
+ ...
+ 21. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[Year]],
+ dateTimeResult.[[Month]], dateTimeResult.[[Day]], dateTimeResult.[[Hour]],
+ dateTimeResult.[[Minute]], dateTimeResult.[[Second]], dateTimeResult.[[Millisecond]],
+ dateTimeResult.[[Microsecond]], dateTimeResult.[[Nanosecond]], option, offsetNanoseconds,
+ timeZone, disambiguation, offset, match exactly).
+ ...
+features: [Temporal]
+---*/
+
+let zdt = new Temporal.ZonedDateTime(0n, "UTC");
+
+let temporalZonedDateTimeLike = {
+ year: -271821,
+ month: 4,
+ day: 19,
+ hour: 1,
+ minute: 0,
+ second: 0,
+ millisecond: 0,
+ microsecond: 0,
+ nanosecond: 0,
+ offset: "+00",
+};
+
+let options = {
+ offset: "use",
+};
+
+assert.throws(RangeError, () => zdt.with(temporalZonedDateTimeLike, options));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time.js
new file mode 100644
index 0000000000..fe7a12d195
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/with/zoned-datetime-like-at-minimum-date-time.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: >
+ Throws a RangeError for the minimum date/value with UTC offset.
+info: |
+ Temporal.ZonedDateTime.prototype.with ( temporalZonedDateTimeLike [ , options ] )
+ ...
+ 21. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[Year]],
+ dateTimeResult.[[Month]], dateTimeResult.[[Day]], dateTimeResult.[[Hour]],
+ dateTimeResult.[[Minute]], dateTimeResult.[[Second]], dateTimeResult.[[Millisecond]],
+ dateTimeResult.[[Microsecond]], dateTimeResult.[[Nanosecond]], option, offsetNanoseconds,
+ timeZone, disambiguation, offset, match exactly).
+ ...
+features: [Temporal]
+---*/
+
+let zdt = new Temporal.ZonedDateTime(0n, "UTC");
+
+let temporalZonedDateTimeLike = {
+ year: -271821,
+ month: 4,
+ day: 19,
+ hour: 1,
+ minute: 0,
+ second: 0,
+ millisecond: 0,
+ microsecond: 0,
+ nanosecond: 0,
+};
+
+assert.throws(RangeError, () => zdt.with(temporalZonedDateTimeLike));
+
+reportCompare(0, 0);