summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype
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/TimeZone/prototype
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/TimeZone/prototype')
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/constructor.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-object.js106
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-primitive.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-valid.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/id-wrong-type.js41
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-case-insensitive.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-datetime.js64
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-multiple-offsets.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-builtin-calendar-no-array-iteration.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-number.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-case-insensitive.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-leap-second.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-number.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-string.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-year-zero.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-calendar-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-date-with-utc-offset.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-calendar.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-wrong-type.js43
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-datefromfields-called-with-null-prototype-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/constructor-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js35
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/duplicate-calendar-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/getpossibleinstantsfor-called-with-iso8601-calendar.js59
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/leap-second.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-object.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/order-of-operations.js109
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/proto-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-calendar-annotation.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-date-with-utc-offset.js52
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-invalid.js69
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-calendar.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string-limits.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/leap-second.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-calendar-annotation.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-date-with-utc-offset.js52
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-invalid.js69
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-calendar.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string-limits.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/leap-second.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-calendar-annotation.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-date-with-utc-offset.js52
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-invalid.js69
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-calendar.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string-limits.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/leap-second.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-object-tostring.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-calendar-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-date-with-utc-offset.js53
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-invalid.js69
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-calendar.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-separators.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-zone-annotation.js35
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-unknown-annotation.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js42
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-case-insensitive.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-number.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string-leap-second.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js42
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-wrong-type.js42
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-limits.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-sub-minute-offset.js68
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/leap-second.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/limits.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-builtin-calendar-no-array-iteration.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-number.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-case-insensitive.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-leap-second.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-number.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-string.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-year-zero.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-calendar-annotation.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-date-with-utc-offset.js49
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-calendar.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-separators.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-zone-annotation.js35
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-unknown-annotation.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-wrong-type.js43
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-datefromfields-called-with-null-prototype-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/constructor-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/duplicate-calendar-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/fixed-offset-near-date-time-limits.js57
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/leap-second.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/proto-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-calendar-annotation.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-date-with-utc-offset.js52
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-invalid.js69
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-calendar.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string-limits.js47
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/leap-second.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/branding.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/custom-timezone.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/prop-desc.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/returns-identifier-slot.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/shell.js0
284 files changed, 8190 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/constructor.js
new file mode 100644
index 0000000000..b84be5c78b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/constructor.js
@@ -0,0 +1,20 @@
+// |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.timezone.prototype.constructor
+description: Test for Temporal.TimeZone.prototype.constructor.
+info: The initial value of Temporal.TimeZone.prototype.constructor is %Temporal.TimeZone%.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.TimeZone.prototype, "constructor", {
+ value: Temporal.TimeZone,
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-object.js
new file mode 100644
index 0000000000..196f32b1a9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-object.js
@@ -0,0 +1,106 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: Tests that objects can be compared for equality
+features: [Temporal]
+---*/
+
+class CustomTimeZone extends Temporal.TimeZone {
+ constructor(id) {
+ super("UTC");
+ this._id = id;
+ }
+ get id() {
+ return this._id;
+ }
+}
+
+const objectsEqualUTC = [
+ new Temporal.TimeZone("UTC"),
+ new CustomTimeZone("UTC"),
+ { id: "UTC", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ new Temporal.ZonedDateTime(0n, "UTC")
+];
+
+const tzUTC = new Temporal.TimeZone("UTC");
+
+for (const object of objectsEqualUTC) {
+ const result = tzUTC.equals(object);
+ assert.sameValue(result, true, `Receiver ${tzUTC.id} should equal argument ${object.id}`);
+}
+
+const objectsEqual0000 = [
+ new Temporal.TimeZone("+00:00"),
+ new Temporal.TimeZone("+0000"),
+ new Temporal.TimeZone("+00"),
+ new CustomTimeZone("+00:00"),
+ new CustomTimeZone("+0000"),
+ new CustomTimeZone("+00"),
+ { id: "+00:00", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ { id: "+0000", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ { id: "+00", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ new Temporal.ZonedDateTime(0n, "+00:00"),
+ new Temporal.ZonedDateTime(0n, "+0000"),
+ new Temporal.ZonedDateTime(0n, "+00"),
+ "+00:00",
+ "+0000",
+ "+00"
+];
+
+const tz0000ToTest = [
+ new Temporal.TimeZone("+00:00"),
+ new Temporal.TimeZone("+0000"),
+ new Temporal.TimeZone("+00"),
+ new CustomTimeZone("+00:00"),
+ new CustomTimeZone("+0000"),
+ new CustomTimeZone("+00")
+];
+
+for (const arg of objectsEqual0000) {
+ for (const receiver of tz0000ToTest) {
+ const result = receiver.equals(arg);
+ assert.sameValue(result, true, `Receiver ${receiver.id} should equal argument ${arg.id ?? arg}`);
+ }
+}
+
+const objectsNotEqual = [
+ new Temporal.TimeZone("+00:00"),
+ new CustomTimeZone("+00:00"),
+ new CustomTimeZone("Etc/Custom"),
+ { id: "+00:00", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ { id: "Etc/Custom", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null },
+ new Temporal.ZonedDateTime(0n, "+00:00"),
+ "UTC"
+];
+
+const customObjectsToTest = [tzUTC, new CustomTimeZone("YouTeeSee"), new CustomTimeZone("+01:00")];
+
+for (const arg of objectsNotEqual) {
+ for (const receiver of customObjectsToTest) {
+ if (arg === "UTC" && receiver === tzUTC) continue;
+ const result = receiver.equals(arg);
+ assert.sameValue(result, false, `Receiver ${receiver.id} should not equal argument ${arg.id ?? arg}`);
+ }
+}
+
+// Custom object IDs are compared case-sensitively
+const classInstanceCustomId = new CustomTimeZone("Moon/Cheese");
+const classInstanceSameCaseCustomId = new CustomTimeZone("Moon/Cheese");
+const classInstanceDifferentCaseCustomId = new CustomTimeZone("MoOn/CHEESe");
+
+const plainObjectSameCaseCustomId = { id: "Moon/Cheese", getPossibleInstantsFor: null, getOffsetNanosecondsFor: null };
+const plainObjectDifferentCaseCustomId = {
+ id: "MoOn/CHEESe",
+ getPossibleInstantsFor: null,
+ getOffsetNanosecondsFor: null
+};
+
+assert.sameValue(classInstanceCustomId.equals(classInstanceSameCaseCustomId), true);
+assert.sameValue(classInstanceCustomId.equals(classInstanceDifferentCaseCustomId), false);
+assert.sameValue(classInstanceCustomId.equals(plainObjectSameCaseCustomId), true);
+assert.sameValue(classInstanceCustomId.equals(plainObjectDifferentCaseCustomId), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-primitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-primitive.js
new file mode 100644
index 0000000000..023206985d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-primitive.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.from
+description: Exceptions thrown if a value is passed that converts to an invalid string
+features: [Temporal]
+---*/
+
+const primitives = [
+ undefined,
+ null,
+ true,
+ "string",
+ "local",
+ "Z",
+ "-00:00[UTC]",
+ "+00:01.1",
+ "-01.1",
+ "1994-11-05T08:15:30+25:00",
+ "1994-11-05T13:15:30-25:00",
+ 7,
+ 4.2,
+ 12n
+];
+
+const tzUTC = new Temporal.TimeZone("UTC");
+for (const primitive of primitives) {
+ assert.throws(typeof primitive === "string" ? RangeError : TypeError, () => tzUTC.equals(primitive));
+}
+
+const symbol = Symbol();
+assert.throws(TypeError, () => tzUTC.equals(symbol));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-valid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-valid.js
new file mode 100644
index 0000000000..79af622fe4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/argument-valid.js
@@ -0,0 +1,48 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.from
+description: Built-in time zones are compared correctly out of valid strings
+features: [Temporal]
+---*/
+
+const validsEqual = [
+ ["+0330", "+03:30"],
+ ["-0650", "-06:50"],
+ ["-08", "-08:00"],
+ ["\u221201:00", "-01:00"],
+ ["\u22120650", "-06:50"],
+ ["\u221208", "-08:00"],
+ ["1994-11-05T08:15:30-05:00", "-05:00"],
+ ["1994-11-05T08:15:30\u221205:00", "-05:00"],
+ ["1994-11-05T13:15:30Z", "UTC"]
+];
+
+for (const [valid, canonical] of validsEqual) {
+ const tzValid = Temporal.TimeZone.from(valid);
+ const tzCanonical = Temporal.TimeZone.from(canonical);
+ assert.sameValue(tzValid.equals(canonical), true);
+ assert.sameValue(tzCanonical.equals(valid), true);
+}
+
+const validsNotEqual = [
+ ["+0330", "+03:31"],
+ ["-0650", "-06:51"],
+ ["-08", "-08:01"],
+ ["\u221201:00", "-01:01"],
+ ["\u22120650", "-06:51"],
+ ["\u221208", "-08:01"],
+ ["1994-11-05T08:15:30-05:00", "-05:01"],
+ ["1994-11-05T08:15:30\u221205:00", "-05:01"]
+];
+
+for (const [valid, canonical] of validsNotEqual) {
+ const tzValid = Temporal.TimeZone.from(valid);
+ const tzCanonical = Temporal.TimeZone.from(canonical);
+ assert.sameValue(tzValid.equals(canonical), false);
+ assert.sameValue(tzCanonical.equals(valid), false);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/branding.js
new file mode 100644
index 0000000000..5673b192e4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/branding.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const equals = Temporal.TimeZone.prototype.equals;
+
+assert.sameValue(typeof equals, "function");
+
+const args = ["UTC"];
+
+assert.throws(TypeError, () => equals.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => equals.apply(null, args), "null");
+assert.throws(TypeError, () => equals.apply(true, args), "true");
+assert.throws(TypeError, () => equals.apply("", args), "empty string");
+assert.throws(TypeError, () => equals.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => equals.apply(1, args), "1");
+assert.throws(TypeError, () => equals.apply({}, args), "plain object");
+assert.throws(TypeError, () => equals.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => equals.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/builtin.js
new file mode 100644
index 0000000000..02c46c0d3b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/builtin.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: >
+ Tests that Temporal.TimeZone.prototype.equals
+ 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.TimeZone.prototype.equals),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.equals),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.equals),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.equals.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/id-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/id-wrong-type.js
new file mode 100644
index 0000000000..b8fa629020
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/id-wrong-type.js
@@ -0,0 +1,41 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: TypeError thrown if time zone reports an id that is not a String
+features: [Temporal]
+---*/
+
+class CustomTimeZone extends Temporal.TimeZone {
+ constructor(id) {
+ super("UTC");
+ this._id = id;
+ }
+ get id() {
+ return this._id;
+ }
+}
+
+[
+ undefined,
+ null,
+ true,
+ -1000,
+ Symbol(),
+ 3600_000_000_000n,
+ {},
+ {
+ valueOf() {
+ return 3600_000_000_000;
+ }
+ }
+].forEach((wrongId) => {
+ const timeZoneWrong = new CustomTimeZone(wrongId);
+ const timeZoneOK = new Temporal.TimeZone('UTC');
+ assert.throws(TypeError, () => timeZoneWrong.equals(timeZoneOK));
+ assert.throws(TypeError, () => timeZoneOK.equals(timeZoneWrong));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/length.js
new file mode 100644
index 0000000000..61c65195ff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: Temporal.TimeZone.prototype.equals.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.TimeZone.prototype.equals, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/name.js
new file mode 100644
index 0000000000..df1828acc7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/name.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: Temporal.TimeZone.prototype.equals.name is "equals".
+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.TimeZone.prototype.equals, "name", {
+ value: "equals",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/not-a-constructor.js
new file mode 100644
index 0000000000..e01067b313
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/not-a-constructor.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: >
+ Temporal.TimeZone.prototype.equals 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.TimeZone.prototype.equals();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.equals), false,
+ "isConstructor(Temporal.TimeZone.prototype.equals)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/prop-desc.js
new file mode 100644
index 0000000000..deb16a6e1c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/prop-desc.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.equals
+description: The "equals" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.equals,
+ "function",
+ "`typeof TimeZone.prototype.equals` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "equals", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/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/TimeZone/prototype/equals/timezone-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-case-insensitive.js
new file mode 100644
index 0000000000..28d4a0de6f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-case-insensitive.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.equals
+description: Time zone names are case insensitive
+features: [Temporal]
+---*/
+
+const timeZone = 'UtC';
+const result = Temporal.TimeZone.from(timeZone);
+assert.sameValue(result.equals(timeZone), true);
+assert.sameValue(result.equals("+00:00"), false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-datetime.js
new file mode 100644
index 0000000000..56cafca99f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-datetime.js
@@ -0,0 +1,64 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.equals
+description: Conversion of ISO date-time strings to the argument of Temporal.TimeZone.prototype.equals
+features: [Temporal]
+---*/
+
+let tzUTC = Temporal.TimeZone.from("UTC");
+let arg = "2021-08-19T17:30";
+assert.throws(RangeError, () => tzUTC.equals(arg), "bare date-time string is not a time zone");
+
+[
+ "2021-08-19T17:30-07:00:01",
+ "2021-08-19T17:30-07:00:00",
+ "2021-08-19T17:30-07:00:00.1",
+ "2021-08-19T17:30-07:00:00.0",
+ "2021-08-19T17:30-07:00:00.01",
+ "2021-08-19T17:30-07:00:00.00",
+ "2021-08-19T17:30-07:00:00.001",
+ "2021-08-19T17:30-07:00:00.000",
+ "2021-08-19T17:30-07:00:00.0001",
+ "2021-08-19T17:30-07:00:00.0000",
+ "2021-08-19T17:30-07:00:00.00001",
+ "2021-08-19T17:30-07:00:00.00000",
+ "2021-08-19T17:30-07:00:00.000001",
+ "2021-08-19T17:30-07:00:00.000000",
+ "2021-08-19T17:30-07:00:00.0000001",
+ "2021-08-19T17:30-07:00:00.0000000",
+ "2021-08-19T17:30-07:00:00.00000001",
+ "2021-08-19T17:30-07:00:00.00000000",
+ "2021-08-19T17:30-07:00:00.000000001",
+ "2021-08-19T17:30-07:00:00.000000000",
+].forEach((timeZone) => {
+ assert.throws(
+ RangeError,
+ () => tzUTC.equals(timeZone),
+ `ISO string ${timeZone} with a sub-minute offset is not a valid time zone`
+ );
+});
+
+arg = "2021-08-19T17:30Z";
+tzUTC = Temporal.TimeZone.from(arg);
+assert.sameValue(tzUTC.equals(arg), true, "date-time + Z is UTC time zone");
+
+arg = "2021-08-19T17:30-07:00";
+tzUTC = Temporal.TimeZone.from(arg);
+assert.sameValue(tzUTC.equals(arg), true, "date-time + offset is the offset time zone");
+
+arg = "2021-08-19T17:30[UTC]";
+tzUTC = Temporal.TimeZone.from(arg);
+assert.sameValue(tzUTC.equals(arg), true, "date-time + IANA annotation is the IANA time zone");
+
+arg = "2021-08-19T17:30Z[UTC]";
+tzUTC = Temporal.TimeZone.from(arg);
+assert.sameValue(tzUTC.equals(arg), true, "date-time + Z + IANA annotation is the IANA time zone");
+
+arg = "2021-08-19T17:30-07:00[UTC]";
+tzUTC = Temporal.TimeZone.from(arg);
+assert.sameValue(tzUTC.equals(arg), true, "date-time + offset + IANA annotation is the IANA time zone");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-multiple-offsets.js
new file mode 100644
index 0000000000..2ac68213de
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-string-multiple-offsets.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.from
+description: Time zone strings with UTC offset fractional part are not confused with time fractional part
+features: [Temporal]
+---*/
+
+const timeZone = "2021-08-19T17:30:45.123456789-12:12[+01:46]";
+
+const result = Temporal.TimeZone.from(timeZone);
+assert.sameValue(result.equals("+01:46"), true, "Time zone string determined from bracket name");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-wrong-type.js
new file mode 100644
index 0000000000..a0031d3629
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/equals/timezone-wrong-type.js
@@ -0,0 +1,46 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Justin Grant. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.from
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or object for TimeZone
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const rangeErrorTests = [
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"]
+];
+
+const tzUTC = new Temporal.TimeZone("UTC");
+
+for (const [timeZone, description] of rangeErrorTests) {
+ assert.throws(
+ typeof timeZone === "string" ? RangeError : TypeError,
+ () => tzUTC.equals(timeZone),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "object not implementing time zone protocol"],
+ [new Temporal.Calendar("iso8601"), "calendar instance"]
+];
+
+for (const [timeZone, description] of typeErrorTests) {
+ assert.throws(
+ TypeError,
+ () => tzUTC.equals(timeZone),
+ `${description} is not a valid object and does not convert to a string`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..86aeca4e6f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-builtin-calendar-no-array-iteration.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getinstantfor
+description: >
+ Calling the method with a property bag argument 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.TimeZone("UTC");
+// Patch getPossibleInstantsFor to allow the spec-mandated observable array
+// iteration in the GetPossibleInstantsFor AO.
+instance.getPossibleInstantsFor = function (...args) {
+ const instants = Temporal.TimeZone.prototype.getPossibleInstantsFor.apply(this, args);
+ instants[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+ return instants;
+}
+
+const arg = { year: 2000, month: 5, day: 2, hour: 21, minute: 43, second: 5, calendar: "iso8601" };
+instance.getInstantFor(arg);
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js
new file mode 100644
index 0000000000..25129f6bbd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-not-datetime.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getinstantfor
+description: Appropriate error thrown when argument cannot be converted to Temporal.PlainDateTime
+features: [Temporal]
+---*/
+
+const timeZone = Temporal.TimeZone.from("UTC");
+assert.throws(TypeError, () => timeZone.getInstantFor(undefined), "undefined");
+assert.throws(TypeError, () => timeZone.getInstantFor(null), "null");
+assert.throws(TypeError, () => timeZone.getInstantFor(true), "boolean");
+assert.throws(RangeError, () => timeZone.getInstantFor(""), "empty string");
+assert.throws(TypeError, () => timeZone.getInstantFor(Symbol()), "Symbol");
+assert.throws(TypeError, () => timeZone.getInstantFor(5), "number");
+assert.throws(TypeError, () => timeZone.getInstantFor(5n), "bigint");
+assert.throws(TypeError, () => timeZone.getInstantFor({ year: 2020 }), "plain object");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-number.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-number.js
new file mode 100644
index 0000000000..77e4ea585a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-number.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getinstantfor
+description: A number cannot be used in place of a Temporal.PlainDateTime
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const numbers = [
+ 1,
+ 19761118,
+ -19761118,
+ 1234567890,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => instance.getInstantFor(arg),
+ `A number (${arg}) is not a valid ISO string for PlainDateTime`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.js
new file mode 100644
index 0000000000..5feb991897
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-plaindate.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.timezone.prototype.getinstantfor
+description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots
+info: |
+ sec-temporal.timezone.prototype.getinstantfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.b:
+ b. If _item_ has an [[InitializedTemporalDate]] internal slot, then
+ i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => {
+ const timezone = new Temporal.TimeZone("UTC");
+ const result = timezone.getInstantFor(date);
+ assert.sameValue(result.epochNanoseconds, 957_225_600_000_000_000n, "epochNanoseconds result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-case-insensitive.js
new file mode 100644
index 0000000000..baa227029c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-case-insensitive.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+description: The calendar name is case-insensitive
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "IsO8601";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getInstantFor(arg);
+assert.sameValue(result.epochNanoseconds, 217_123_200_000_000_000n, "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-leap-second.js
new file mode 100644
index 0000000000..8dbefc0285
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-leap-second.js
@@ -0,0 +1,23 @@
+// |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.timezone.prototype.getinstantfor
+description: Leap second is a valid ISO string for a calendar in a property bag
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "2016-12-31T23:59:60";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getInstantFor(arg);
+assert.sameValue(
+ result.epochNanoseconds,
+ 217_123_200_000_000_000n,
+ "leap second is a valid ISO string for calendar"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-number.js
new file mode 100644
index 0000000000..5c799c9c6c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-number.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getinstantfor
+description: A number as calendar in a property bag is not accepted
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const numbers = [
+ 1,
+ 19970327,
+ -19970327,
+ 1234567890,
+];
+
+for (const calendar of numbers) {
+ const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+ assert.throws(
+ TypeError,
+ () => instance.getInstantFor(arg),
+ "Numbers cannot be used as a calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-string.js
new file mode 100644
index 0000000000..050000cc46
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-string.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+description: A calendar ID is valid input for Calendar
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "iso8601";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getInstantFor(arg);
+assert.sameValue(result.epochNanoseconds, 217_123_200_000_000_000n, `Calendar created from string "${calendar}"`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-wrong-type.js
new file mode 100644
index 0000000000..d07432774c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getinstantfor
+description: >
+ Appropriate error thrown when a calendar property from a property bag cannot
+ be converted to a calendar object or string
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const timeZone = new Temporal.TimeZone("UTC");
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [1n, "bigint"],
+];
+
+for (const [calendar, description] of primitiveTests) {
+ const arg = { year: 2019, monthCode: "M11", day: 1, calendar };
+ assert.throws(
+ typeof calendar === 'string' ? RangeError : TypeError,
+ () => instance.getInstantFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object that doesn't implement the protocol"],
+ [new Temporal.TimeZone("UTC"), "time zone instance"],
+ [Temporal.Calendar, "Temporal.Calendar, object"],
+ [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields()
+];
+
+for (const [calendar, description] of typeErrorTests) {
+ const arg = { year: 2019, monthCode: "M11", day: 1, calendar };
+ assert.throws(TypeError, () => instance.getInstantFor(arg), `${description} is not a valid property bag and does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-year-zero.js
new file mode 100644
index 0000000000..8065dd55fe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-propertybag-calendar-year-zero.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getinstantfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-10-31",
+ "-000000-10-31T17:45",
+ "-000000-10-31T17:45Z",
+ "-000000-10-31T17:45+01:00",
+ "-000000-10-31T17:45+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..1bb66f7648
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-calendar-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getinstantfor
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[u-ca=iso8601]", "without time zone"],
+ ["1976-11-18T15:23[UTC][u-ca=iso8601]", "with time zone"],
+ ["1976-11-18T15:23[!u-ca=iso8601]", "with ! and no time zone"],
+ ["1976-11-18T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"],
+ ["1976-11-18T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getInstantFor(arg);
+
+ assert.sameValue(
+ result.epochNanoseconds,
+ 217_178_580_000_000_000n,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..afc68a8834
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getinstantfor
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00[!foo=bar]",
+ "1970-01-01T00:00[UTC][!foo=bar]",
+ "1970-01-01T00:00[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..647003b0b1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-date-with-utc-offset.js
@@ -0,0 +1,48 @@
+// |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.timezone.prototype.getinstantfor
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1976-11-18T15:23+00:00",
+ "1976-11-18T15:23+00:00[UTC]",
+ "1976-11-18T15:23+00:00[!UTC]",
+ "1976-11-18T15:23-02:30[America/St_Johns]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getInstantFor(arg);
+
+ assert.sameValue(
+ result.epochNanoseconds,
+ 217_178_580_000_000_000n,
+ `"${arg}" is a valid UTC offset with time for PlainDateTime`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ `"${arg}" UTC offset without time is not valid for PlainDateTime`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..caa6556187
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-calendar.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getinstantfor
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+ "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..94425d1a21
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getinstantfor
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00[UTC][UTC]",
+ "1970-01-01T00:00[!UTC][UTC]",
+ "1970-01-01T00:00[UTC][!UTC]",
+ "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-separators.js
new file mode 100644
index 0000000000..dc5b4da151
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-separators.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getinstantfor
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23", "uppercase T"],
+ ["1976-11-18t15:23", "lowercase T"],
+ ["1976-11-18 15:23", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getInstantFor(arg);
+
+ assert.sameValue(
+ result.epochNanoseconds,
+ 217_178_580_000_000_000n,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..c9bbd70bf1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-time-zone-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getinstantfor
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[Asia/Kolkata]", "named, with no offset"],
+ ["1976-11-18T15:23[!Europe/Vienna]", "named, with ! and no offset"],
+ ["1976-11-18T15:23[+00:00]", "numeric, with no offset"],
+ ["1976-11-18T15:23[!-02:30]", "numeric, with ! and no offset"],
+ ["1976-11-18T15:23+00:00[UTC]", "named, with offset"],
+ ["1976-11-18T15:23+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1976-11-18T15:23+00:00[+01:00]", "numeric, with offset"],
+ ["1976-11-18T15:23+00:00[!-08:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getInstantFor(arg);
+
+ assert.sameValue(
+ result.epochNanoseconds,
+ 217_178_580_000_000_000n,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..7c8a57e644
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-unknown-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getinstantfor
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[foo=bar]", "alone"],
+ ["1976-11-18T15:23[UTC][foo=bar]", "with time zone"],
+ ["1976-11-18T15:23[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1976-11-18T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1976-11-18T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getInstantFor(arg);
+
+ assert.sameValue(
+ result.epochNanoseconds,
+ 217_178_580_000_000_000n,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.js
new file mode 100644
index 0000000000..8361128f7e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-string-with-utc-designator.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.timezone.prototype.getinstantfor
+description: RangeError thrown if a string with UTC designator is used as a PlainDateTime
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "2019-10-01T09:00:00Z",
+ "2019-10-01T09:00:00Z[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ "String with UTC designator should not be valid as a PlainDateTime"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-wrong-type.js
new file mode 100644
index 0000000000..dbc90d6ccd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-wrong-type.js
@@ -0,0 +1,43 @@
+// |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.timezone.prototype.getinstantfor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or property bag for PlainDateTime
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [1n, "bigint"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === 'string' ? RangeError : TypeError,
+ () => instance.getInstantFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object"],
+ [Temporal.PlainDateTime, "Temporal.PlainDateTime, object"],
+ [Temporal.PlainDateTime.prototype, "Temporal.PlainDateTime.prototype, object"],
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getInstantFor(arg), `${description} is not a valid property bag and does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js
new file mode 100644
index 0000000000..fc47684fd3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-balance-negative-time-units.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getinstantfor
+description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime
+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-balanceisodatetime step 1:
+ 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_).
+ sec-temporal-builtintimezonegetplaindatetimefor step 3:
+ 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_).
+ sec-temporal-totemporaldatetime step 3.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]).
+ sec-temporal.timezone.prototype.getinstantfor step 3:
+ 3. Set _dateTime_ ? ToTemporalDateTime(_dateTime_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+// This code path is encountered if the time zone offset is negative and its
+// absolute value in nanoseconds is greater than the nanosecond field of the
+// exact time's epoch parts
+const tz = TemporalHelpers.specificOffsetTimeZone(-2);
+const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz);
+
+const conversionTimeZone = new Temporal.TimeZone("UTC"); // should not be used to interpret the argument
+const instant = conversionTimeZone.getInstantFor(datetime);
+
+assert.sameValue(instant.epochNanoseconds, 3661_001_000_999n);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.js
new file mode 100644
index 0000000000..25e42c9193
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-negative-epochnanoseconds.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.timezone.prototype.getinstantfor
+description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch
+info: |
+ sec-temporal-getisopartsfromepoch step 1:
+ 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>.
+ sec-temporal-builtintimezonegetplaindatetimefor step 2:
+ 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC");
+
+// This code path shows up anywhere we convert an exact time, before the Unix
+// epoch, with nonzero microseconds or nanoseconds, into a wall time.
+
+const instance = new Temporal.TimeZone("UTC");
+const result = instance.getInstantFor(datetime);
+assert.sameValue(result.epochNanoseconds, -13849764_999_999_999n);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
new file mode 100644
index 0000000000..33e6af18f2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(RangeError, () => builtinTimeZone.getInstantFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
new file mode 100644
index 0000000000..d58be69ae8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
@@ -0,0 +1,23 @@
+// |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.timezone.prototype.getinstantfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ timeZone.getOffsetNanosecondsFor = notCallable;
+ assert.throws(
+ TypeError,
+ () => builtinTimeZone.getInstantFor(datetime),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
new file mode 100644
index 0000000000..2a9b963652
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(RangeError, () => builtinTimeZone.getInstantFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js
new file mode 100644
index 0000000000..3aaeec2514
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.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.timezone.prototype.getinstantfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(TypeError, () => builtinTimeZone.getInstantFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.js
new file mode 100644
index 0000000000..f8613922bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/balance-negative-time-units.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.timezone.prototype.getinstantfor
+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.timezone.prototype.getinstantfor step 6:
+ 6. Return ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dateTime_, _disambiguation_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const shiftInstant = new Temporal.Instant(3661_001_001_001n);
+const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, 2);
+const datetime = new Temporal.PlainDateTime(1970, 1, 1, 1, 1, 1, 1, 1, 1);
+
+// This code path is encountered if disambiguation is `earlier` and the shift is
+// a spring-forward change
+tz.getInstantFor(datetime, { disambiguation: "earlier" });
+
+const expected = [
+ "1970-01-01T01:01:01.001001001",
+ "1970-01-01T01:01:01.001000999",
+];
+assert.compareArray(tz.getPossibleInstantsForCalledWith, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/branding.js
new file mode 100644
index 0000000000..d5ea3f0c76
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getInstantFor = Temporal.TimeZone.prototype.getInstantFor;
+
+assert.sameValue(typeof getInstantFor, "function");
+
+const args = [new Temporal.PlainDateTime(2022, 6, 22)];
+
+assert.throws(TypeError, () => getInstantFor.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getInstantFor.apply(null, args), "null");
+assert.throws(TypeError, () => getInstantFor.apply(true, args), "true");
+assert.throws(TypeError, () => getInstantFor.apply("", args), "empty string");
+assert.throws(TypeError, () => getInstantFor.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getInstantFor.apply(1, args), "1");
+assert.throws(TypeError, () => getInstantFor.apply({}, args), "plain object");
+assert.throws(TypeError, () => getInstantFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getInstantFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/builtin.js
new file mode 100644
index 0000000000..709f4d3c30
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: >
+ Tests that Temporal.TimeZone.prototype.getInstantFor
+ 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.TimeZone.prototype.getInstantFor),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getInstantFor),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getInstantFor),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getInstantFor.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-datefromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..b3650982ca
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-datefromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+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.TimeZone("UTC");
+const arg = { year: 2000, month: 5, day: 2, calendar };
+instance.getInstantFor(arg);
+assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.js
new file mode 100644
index 0000000000..c4a2b8bc1f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-fields-iterable.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.timezone.prototype.getinstantfor
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.timezone.prototype.getinstantfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.c:
+ c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"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 timeZone = new Temporal.TimeZone("UTC");
+timeZone.getInstantFor({ year: 2000, month: 5, day: 2, calendar });
+
+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/TimeZone/prototype/getInstantFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.js
new file mode 100644
index 0000000000..54f820bd2f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/calendar-temporal-object.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.timezone.prototype.getinstantfor
+description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
+info: |
+ sec-temporal.timezone.prototype.getinstantfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.c:
+ c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ sec-temporal-gettemporalcalendarwithisodefault step 2:
+ 2. Return ? ToTemporalCalendarWithISODefault(_calendar_).
+ sec-temporal-totemporalcalendarwithisodefault step 2:
+ 3. Return ? ToTemporalCalendar(_temporalCalendarLike_).
+ sec-temporal-totemporalcalendar step 1.a:
+ a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return _temporalCalendarLike_.[[Calendar]].
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => {
+ const timeZone = new Temporal.TimeZone("UTC");
+ timeZone.getInstantFor({ year: 2000, month: 5, day: 2, calendar: temporalObject });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..0404044e4d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/constructor-in-calendar-fields.js
@@ -0,0 +1,17 @@
+// |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.timezone.prototype.getinstantfor
+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 arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar};
+const instance = new Temporal.TimeZone("UTC");
+
+assert.throws(RangeError, () => instance.getInstantFor(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..2f1c3f3fd2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.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.timezone.prototype.getinstantfor
+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.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+assert.throws(RangeError, () => timeZone.getInstantFor(datetime, { disambiguation: "other string" }));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js
new file mode 100644
index 0000000000..f8874c7227
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-undefined.js
@@ -0,0 +1,35 @@
+// |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.timezone.prototype.getinstantfor
+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.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardDateTime = new Temporal.PlainDateTime(2000, 4, 2, 2, 30);
+const fallBackDateTime = new Temporal.PlainDateTime(2000, 10, 29, 1, 30);
+
+[
+ [springForwardDateTime, 954671400_000_000_000n],
+ [fallBackDateTime, 972808200_000_000_000n],
+].forEach(([datetime, expected]) => {
+ const explicit = timeZone.getInstantFor(datetime, { disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const implicit = timeZone.getInstantFor(datetime, {});
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const lambda = timeZone.getInstantFor(datetime, () => {});
+ assert.sameValue(lambda.epochNanoseconds, expected, "default disambiguation is compatible");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..8184f7cce9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.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.timezone.prototype.getinstantfor
+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.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => timeZone.getInstantFor(datetime, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..b6a8d452a8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/duplicate-calendar-fields.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getinstantfor
+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'], ['day'], ['hour'], ['microsecond'], ['millisecond'], ['minute'], ['month'], ['monthCode'], ['nanosecond'], ['second'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar };
+ const instance = new Temporal.TimeZone("UTC");
+
+ assert.throws(RangeError, () => instance.getInstantFor(arg));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/getpossibleinstantsfor-called-with-iso8601-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/getpossibleinstantsfor-called-with-iso8601-calendar.js
new file mode 100644
index 0000000000..b78f801c25
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/getpossibleinstantsfor-called-with-iso8601-calendar.js
@@ -0,0 +1,59 @@
+// |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.timezone.prototype.getinstantfor
+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();
+ timeZone.getInstantFor(new Temporal.PlainDateTime(2000, 3, 4, 12, 34, 56, 0, 0, 0, nonBuiltinISOCalendar), { 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/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..6916cead64
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/infinity-throws-rangeerror.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.
+
+/*---
+description: Throws if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.timezone.prototype.getinstantfor
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 };
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => {
+ assert.throws(RangeError, () => instance.getInstantFor({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
+ assert.throws(RangeError, () => instance.getInstantFor({ ...base, [prop]: obj }));
+ 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/TimeZone/prototype/getInstantFor/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/leap-second.js
new file mode 100644
index 0000000000..e70881059c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/leap-second.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getinstantfor
+description: Leap second is a valid ISO string for PlainDateTime
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let arg = "2016-12-31T23:59:60";
+const result1 = instance.getInstantFor(arg);
+assert.sameValue(
+ result1.epochNanoseconds,
+ 1_483_228_799_000_000_000n,
+ "leap second is a valid ISO string for PlainDateTime"
+);
+
+arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
+const result2 = instance.getInstantFor(arg);
+assert.sameValue(
+ result2.epochNanoseconds,
+ 1_483_228_799_000_000_000n,
+ "second: 60 is ignored in property bag for PlainDateTime"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js
new file mode 100644
index 0000000000..d273fcf2a6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getinstantfor
+description: Temporal.TimeZone.prototype.getInstantFor.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.TimeZone.prototype.getInstantFor, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/name.js
new file mode 100644
index 0000000000..6d07a0e673
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: Temporal.TimeZone.prototype.getInstantFor.name is "getInstantFor".
+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.TimeZone.prototype.getInstantFor, "name", {
+ value: "getInstantFor",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/not-a-constructor.js
new file mode 100644
index 0000000000..f639a9dc89
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: >
+ Temporal.TimeZone.prototype.getInstantFor 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.TimeZone.prototype.getInstantFor();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getInstantFor), false,
+ "isConstructor(Temporal.TimeZone.prototype.getInstantFor)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-object.js
new file mode 100644
index 0000000000..1aa686d763
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: Empty or a function object may be used as options
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const result1 = instance.getInstantFor(new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38), {});
+assert.sameValue(
+ result1.epochNanoseconds, 1572345998000000000n,
+ "options may be an empty plain object"
+);
+
+const result2 = instance.getInstantFor(new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38), () => {});
+assert.sameValue(
+ result2.epochNanoseconds, 1572345998000000000n,
+ "options may be a function object"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-undefined.js
new file mode 100644
index 0000000000..6ddd03d9ef
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-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.timezone.prototype.getinstantfor
+includes: [temporalHelpers.js]
+description: Verify that undefined options are handled correctly.
+features: [BigInt, Temporal]
+---*/
+
+const datetimeEarlier = new Temporal.PlainDateTime(2000, 10, 29, 1, 34, 56, 987, 654, 321);
+const datetimeLater = new Temporal.PlainDateTime(2000, 4, 2, 2, 34, 56, 987, 654, 321);
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+
+[
+ [datetimeEarlier, 972808496987654321n],
+ [datetimeLater, 954671696987654321n],
+].forEach(([datetime, expected]) => {
+ const explicit = timeZone.getInstantFor(datetime, undefined);
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+
+ const implicit = timeZone.getInstantFor(datetime);
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js
new file mode 100644
index 0000000000..4806f4de41
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+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.TimeZone("UTC");
+for (const value of badOptions) {
+ assert.throws(TypeError, () => instance.getInstantFor(new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38), value),
+ `TypeError on wrong options type ${typeof value}`);
+};
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/order-of-operations.js
new file mode 100644
index 0000000000..4705daa151
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/order-of-operations.js
@@ -0,0 +1,109 @@
+// |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.timezone.prototype.getinstantfor
+description: Properties on an object passed to getInstantFor() are accessed in the correct order
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ // GetTemporalCalendarSlotValueWithISODefault
+ "get fields.calendar",
+ "has fields.calendar.dateAdd",
+ "has fields.calendar.dateFromFields",
+ "has fields.calendar.dateUntil",
+ "has fields.calendar.day",
+ "has fields.calendar.dayOfWeek",
+ "has fields.calendar.dayOfYear",
+ "has fields.calendar.daysInMonth",
+ "has fields.calendar.daysInWeek",
+ "has fields.calendar.daysInYear",
+ "has fields.calendar.fields",
+ "has fields.calendar.id",
+ "has fields.calendar.inLeapYear",
+ "has fields.calendar.mergeFields",
+ "has fields.calendar.month",
+ "has fields.calendar.monthCode",
+ "has fields.calendar.monthDayFromFields",
+ "has fields.calendar.monthsInYear",
+ "has fields.calendar.weekOfYear",
+ "has fields.calendar.year",
+ "has fields.calendar.yearMonthFromFields",
+ "has fields.calendar.yearOfWeek",
+ // lookup
+ "get fields.calendar.dateFromFields",
+ "get fields.calendar.fields",
+ // CalendarFields
+ "call fields.calendar.fields",
+ // PrepareTemporalFields
+ "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.second",
+ "get fields.second.valueOf",
+ "call fields.second.valueOf",
+ "get fields.year",
+ "get fields.year.valueOf",
+ "call fields.year.valueOf",
+ // InterpretTemporalDateTimeFields
+ "call fields.calendar.dateFromFields",
+ // ToTemporalDisambiguation
+ "get options.disambiguation",
+ "get options.disambiguation.toString",
+ "call options.disambiguation.toString",
+ // BuiltinTimeZoneGetInstantFor
+ "get this.getPossibleInstantsFor",
+ "call this.getPossibleInstantsFor",
+];
+const actual = [];
+
+const instance = new Temporal.TimeZone("UTC");
+TemporalHelpers.observeProperty(actual, instance, "getPossibleInstantsFor", function getPossibleInstantsFor(...args) {
+ actual.push("call this.getPossibleInstantsFor");
+ return Temporal.TimeZone.prototype.getPossibleInstantsFor.apply(instance, args);
+}, "this");
+
+const fields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 2000,
+ month: 5,
+ monthCode: "M05",
+ day: 2,
+ hour: 12,
+ minute: 34,
+ second: 56,
+ millisecond: 987,
+ microsecond: 654,
+ nanosecond: 321,
+ calendar: TemporalHelpers.calendarObserver(actual, "fields.calendar"),
+}, "fields");
+
+const options = TemporalHelpers.propertyBagObserver(actual, { disambiguation: "compatible" }, "options");
+
+instance.getInstantFor(fields, options);
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/prop-desc.js
new file mode 100644
index 0000000000..444a2d5e2a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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.timezone.prototype.getinstantfor
+description: The "getInstantFor" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getInstantFor,
+ "function",
+ "`typeof TimeZone.prototype.getInstantFor` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getInstantFor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..e9dfd7a26f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/proto-in-calendar-fields.js
@@ -0,0 +1,17 @@
+// |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.timezone.prototype.getinstantfor
+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 arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar};
+const instance = new Temporal.TimeZone("UTC");
+
+assert.throws(RangeError, () => instance.getInstantFor(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.js
new file mode 100644
index 0000000000..87f11aac7f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/read-time-fields-before-datefromfields.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.timezone.prototype.getinstantfor
+description: The time fields are read from the object before being passed to dateFromFields().
+info: |
+ sec-temporal.timezone.prototype.getinstantfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.e:
+ e. Let _result_ 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 timezone = new Temporal.TimeZone("UTC");
+const calendar = TemporalHelpers.calendarMakeInfinityTime();
+const result = timezone.getInstantFor({ year: 1970, month: 1, day: 1, calendar });
+
+assert.sameValue(result.epochNanoseconds, 0n, "epochNanoseconds result");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/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/TimeZone/prototype/getInstantFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.js
new file mode 100644
index 0000000000..3cdf65fe5b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getInstantFor/year-zero.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.timezone.prototype.getinstantfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-12-07",
+ "-000000-12-07T03:24:30",
+ "-000000-12-07T03:24:30+01:00",
+ "-000000-12-07T03:24:30+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getInstantFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..7fc69d9415
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-calendar-annotation.js
@@ -0,0 +1,33 @@
+// |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.timezone.prototype.getnexttransition
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[u-ca=iso8601]", "without time zone"],
+ ["1970-01-01T00:00Z[UTC][u-ca=gregory]", "with time zone"],
+ ["1970-01-01T00:00Z[!u-ca=hebrew]", "with ! and no time zone"],
+ ["1970-01-01T00:00Z[UTC][!u-ca=chinese]", "with ! and time zone"],
+ ["1970-01-01T00:00Z[u-ca=discord]", "annotation is ignored"],
+ ["1970-01-01T00:00Z[!u-ca=discord]", "annotation with ! is ignored"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][u-ca=discord]", "two annotations are ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getNextTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..ea1c71ca90
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getnexttransition
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar]",
+ "1970-01-01T00:00Z[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00Z[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..1521a8cd4d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-date-with-utc-offset.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.timezone.prototype.getnexttransition
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1970-01-01T00Z",
+ "1970-01-01T00Z[UTC]",
+ "1970-01-01T00Z[!UTC]",
+ "1970-01-01T00Z[Europe/Vienna]",
+ "1970-01-01T00+00:00",
+ "1970-01-01T00+00:00[UTC]",
+ "1970-01-01T00+00:00[!UTC]",
+ "1969-12-31T16-08:00[America/Vancouver]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getNextTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `"${arg}" is a valid UTC offset with time for Instant`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ `"${arg}" UTC offset without time is not valid for Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-invalid.js
new file mode 100644
index 0000000000..fdb1c6a0f8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-invalid.js
@@ -0,0 +1,69 @@
+// |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.timezone.prototype.getnexttransition
+description: >
+ RangeError thrown if an invalid ISO string (or syntactically valid ISO string
+ that is not supported) is used as an Instant
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ // invalid ISO strings:
+ "",
+ "invalid iso8601",
+ "2020-01-00T00:00Z",
+ "2020-01-32T00:00Z",
+ "2020-02-30T00:00Z",
+ "2021-02-29T00:00Z",
+ "2020-00-01T00:00Z",
+ "2020-13-01T00:00Z",
+ "2020-01-01TZ",
+ "2020-01-01T25:00:00Z",
+ "2020-01-01T01:60:00Z",
+ "2020-01-01T01:60:61Z",
+ "2020-01-01T00:00Zjunk",
+ "2020-01-01T00:00:00Zjunk",
+ "2020-01-01T00:00:00.000000000Zjunk",
+ "2020-01-01T00:00:00+00:00junk",
+ "2020-01-01T00:00:00+00:00[UTC]junk",
+ "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
+ "02020-01-01T00:00Z",
+ "2020-001-01T00:00Z",
+ "2020-01-001T00:00Z",
+ "2020-01-01T001Z",
+ "2020-01-01T01:001Z",
+ "2020-01-01T01:01:001Z",
+ // valid, but forms not supported in Temporal:
+ "2020-W01-1T00:00Z",
+ "2020-001T00:00Z",
+ "+0002020-01-01T00:00Z",
+ // may be valid in other contexts, but insufficient information for Instant:
+ "2020-01",
+ "+002020-01",
+ "01-01",
+ "2020-W01",
+ "P1Y",
+ "-P12Y",
+ "2020-01-01",
+ "2020-01-01T00",
+ "2020-01-01T00:00",
+ "2020-01-01T00:00:00",
+ "2020-01-01T00:00:00.000000000",
+ // valid, but outside the supported range:
+ "-999999-01-01T00:00Z",
+ "+999999-01-01T00:00Z",
+];
+
+const instance = new Temporal.TimeZone("UTC");
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ `"${arg}" should not be a valid ISO string for an Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..f4aa8ca87f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-calendar.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getnexttransition
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..bfed54adfe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getnexttransition
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[UTC][UTC]",
+ "1970-01-01T00:00Z[!UTC][UTC]",
+ "1970-01-01T00:00Z[UTC][!UTC]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00Z[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-separators.js
new file mode 100644
index 0000000000..153d328c87
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-separators.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getnexttransition
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z", "uppercase T"],
+ ["1970-01-01t00:00Z", "lowercase T"],
+ ["1970-01-01 00:00Z", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getNextTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..efaf2f44b3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-time-zone-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getnexttransition
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[Asia/Kolkata]", "named, with Z"],
+ ["1970-01-01T00:00Z[!Europe/Vienna]", "named, with Z and !"],
+ ["1970-01-01T00:00Z[+00:00]", "numeric, with Z"],
+ ["1970-01-01T00:00Z[!-02:30]", "numeric, with Z and !"],
+ ["1970-01-01T00:00+00:00[UTC]", "named, with offset"],
+ ["1970-01-01T00:00+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1970-01-01T00:00+00:00[-08:00]", "numeric, with offset"],
+ ["1970-01-01T00:00+00:00[!+01:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getNextTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..e465d767d8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-string-unknown-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getnexttransition
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[foo=bar]", "alone"],
+ ["1970-01-01T00:00Z[UTC][foo=bar]", "with time zone"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1970-01-01T00:00Z[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1970-01-01T00:00Z[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getNextTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-wrong-type.js
new file mode 100644
index 0000000000..b89dfe2520
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getnexttransition
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ for Instant
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"],
+ [{}, "plain object"],
+ [Temporal.Instant, "Temporal.Instant, object"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === "string" || (typeof arg === "object" && arg !== null) || typeof arg === "function"
+ ? RangeError
+ : TypeError,
+ () => instance.getNextTransition(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [Temporal.Instant.prototype, "Temporal.Instant.prototype, object"], // fails brand check in toString()
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getNextTransition(arg), `${description} does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.js
new file mode 100644
index 0000000000..74217f32ae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/argument-zoneddatetime.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.timezone.prototype.getnexttransition
+description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant
+info: |
+ sec-temporal.timezone.prototype.getnexttransition step 3:
+ 3. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
+ sec-temporal-totemporalinstant step 1.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalInstantFastPath((datetime) => {
+ const timeZone = Temporal.TimeZone.from("UTC");
+ const result = timeZone.getNextTransition(datetime);
+ assert.sameValue(result, null, "transition result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/branding.js
new file mode 100644
index 0000000000..c78e545d10
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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.timezone.prototype.getnexttransition
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getNextTransition = Temporal.TimeZone.prototype.getNextTransition;
+
+assert.sameValue(typeof getNextTransition, "function");
+
+const args = [new Temporal.Instant(0n)];
+
+assert.throws(TypeError, () => getNextTransition.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getNextTransition.apply(null, args), "null");
+assert.throws(TypeError, () => getNextTransition.apply(true, args), "true");
+assert.throws(TypeError, () => getNextTransition.apply("", args), "empty string");
+assert.throws(TypeError, () => getNextTransition.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getNextTransition.apply(1, args), "1");
+assert.throws(TypeError, () => getNextTransition.apply({}, args), "plain object");
+assert.throws(TypeError, () => getNextTransition.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getNextTransition.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/builtin.js
new file mode 100644
index 0000000000..c63cf94509
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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.timezone.prototype.getnexttransition
+description: >
+ Tests that Temporal.TimeZone.prototype.getNextTransition
+ 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.TimeZone.prototype.getNextTransition),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getNextTransition),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getNextTransition),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getNextTransition.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string-limits.js
new file mode 100644
index 0000000000..769699dcfd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string-limits.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getnexttransition
+description: String arguments at the limit of the representable range
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const minInstantStrings = [
+ "-271821-04-20T00:00Z",
+ "-271821-04-19T23:00-01:00",
+ "-271821-04-19T00:00:00.000000001-23:59:59.999999999",
+];
+for (const str of minInstantStrings) {
+ assert.sameValue(instance.getNextTransition(str), null, `instant string ${str} should be valid`);
+}
+
+const maxInstantStrings = [
+ "+275760-09-13T00:00Z",
+ "+275760-09-13T01:00+01:00",
+ "+275760-09-13T23:59:59.999999999+23:59:59.999999999",
+];
+
+for (const str of maxInstantStrings) {
+ assert.sameValue(instance.getNextTransition(str), null, `instant string ${str} should be valid`);
+}
+
+const outOfRangeInstantStrings = [
+ "-271821-04-19T23:59:59.999999999Z",
+ "-271821-04-19T23:00-00:59:59.999999999",
+ "-271821-04-19T00:00:00-23:59:59.999999999",
+ "-271821-04-19T00:00:00-24:00",
+ "+275760-09-13T00:00:00.000000001Z",
+ "+275760-09-13T01:00+00:59:59.999999999",
+ "+275760-09-14T00:00+23:59:59.999999999",
+ "+275760-09-14T00:00+24:00",
+];
+
+for (const str of outOfRangeInstantStrings) {
+ assert.throws(RangeError, () => instance.getNextTransition(str), `instant string ${str} should not be valid`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.js
new file mode 100644
index 0000000000..eb54738370
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/instant-string.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.timezone.prototype.getnexttransition
+description: Conversion of ISO date-time strings to Temporal.Instant instances
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let str = "1970-01-01T00:00";
+assert.throws(RangeError, () => instance.getNextTransition(str), "bare date-time string is not an instant");
+str = "1970-01-01T00:00[UTC]";
+assert.throws(RangeError, () => instance.getNextTransition(str), "date-time + IANA annotation is not an instant");
+
+// The following are all valid strings so should not throw:
+
+const valids = [
+ "1970-01-01T00:00Z",
+ "1970-01-01T00:00+01:00",
+ "1970-01-01T00:00Z[UTC]",
+ "1970-01-01T00:00+01:00[UTC]",
+ "1970-01-01T00:00Z[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[Etc/Ignored][u-ca=hebrew]",
+];
+for (const str of valids) {
+ const result = instance.getNextTransition(str);
+ assert.sameValue(result, null);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/leap-second.js
new file mode 100644
index 0000000000..e7270bcb82
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/leap-second.js
@@ -0,0 +1,21 @@
+// |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.timezone.prototype.getnexttransition
+description: Leap second is a valid ISO string for Instant
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60Z";
+const result = instance.getNextTransition(arg);
+assert.sameValue(
+ result,
+ null,
+ "leap second is a valid ISO string for Instant"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js
new file mode 100644
index 0000000000..15bda53094
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getnexttransition
+description: Temporal.TimeZone.prototype.getNextTransition.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.TimeZone.prototype.getNextTransition, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/name.js
new file mode 100644
index 0000000000..2da5b50bdd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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.timezone.prototype.getnexttransition
+description: Temporal.TimeZone.prototype.getNextTransition.name is "getNextTransition".
+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.TimeZone.prototype.getNextTransition, "name", {
+ value: "getNextTransition",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/not-a-constructor.js
new file mode 100644
index 0000000000..7685a1cc62
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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.timezone.prototype.getnexttransition
+description: >
+ Temporal.TimeZone.prototype.getNextTransition 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.TimeZone.prototype.getNextTransition();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getNextTransition), false,
+ "isConstructor(Temporal.TimeZone.prototype.getNextTransition)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/prop-desc.js
new file mode 100644
index 0000000000..eeedb1647c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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.timezone.prototype.getnexttransition
+description: The "getNextTransition" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getNextTransition,
+ "function",
+ "`typeof TimeZone.prototype.getNextTransition` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getNextTransition", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/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/TimeZone/prototype/getNextTransition/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.js
new file mode 100644
index 0000000000..0c65c5f647
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getNextTransition/year-zero.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.timezone.prototype.getnexttransition
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-03-30T00:45Z",
+ "-000000-03-30T01:45+01:00",
+ "-000000-03-30T01:45:00+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getNextTransition(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..082b498e9c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-calendar-annotation.js
@@ -0,0 +1,33 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[u-ca=iso8601]", "without time zone"],
+ ["1970-01-01T00:00Z[UTC][u-ca=gregory]", "with time zone"],
+ ["1970-01-01T00:00Z[!u-ca=hebrew]", "with ! and no time zone"],
+ ["1970-01-01T00:00Z[UTC][!u-ca=chinese]", "with ! and time zone"],
+ ["1970-01-01T00:00Z[u-ca=discord]", "annotation is ignored"],
+ ["1970-01-01T00:00Z[!u-ca=discord]", "annotation with ! is ignored"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][u-ca=discord]", "two annotations are ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetNanosecondsFor(arg);
+
+ assert.sameValue(
+ result,
+ 0,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..e90272191d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar]",
+ "1970-01-01T00:00Z[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00Z[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..af93408ea2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-date-with-utc-offset.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.timezone.prototype.getoffsetnanosecondsfor
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1970-01-01T00Z",
+ "1970-01-01T00Z[UTC]",
+ "1970-01-01T00Z[!UTC]",
+ "1970-01-01T00Z[Europe/Vienna]",
+ "1970-01-01T00+00:00",
+ "1970-01-01T00+00:00[UTC]",
+ "1970-01-01T00+00:00[!UTC]",
+ "1969-12-31T16-08:00[America/Vancouver]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getOffsetNanosecondsFor(arg);
+
+ assert.sameValue(
+ result,
+ 0,
+ `"${arg}" is a valid UTC offset with time for Instant`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `"${arg}" UTC offset without time is not valid for Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-invalid.js
new file mode 100644
index 0000000000..ef406af8ff
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-invalid.js
@@ -0,0 +1,69 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: >
+ RangeError thrown if an invalid ISO string (or syntactically valid ISO string
+ that is not supported) is used as an Instant
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ // invalid ISO strings:
+ "",
+ "invalid iso8601",
+ "2020-01-00T00:00Z",
+ "2020-01-32T00:00Z",
+ "2020-02-30T00:00Z",
+ "2021-02-29T00:00Z",
+ "2020-00-01T00:00Z",
+ "2020-13-01T00:00Z",
+ "2020-01-01TZ",
+ "2020-01-01T25:00:00Z",
+ "2020-01-01T01:60:00Z",
+ "2020-01-01T01:60:61Z",
+ "2020-01-01T00:00Zjunk",
+ "2020-01-01T00:00:00Zjunk",
+ "2020-01-01T00:00:00.000000000Zjunk",
+ "2020-01-01T00:00:00+00:00junk",
+ "2020-01-01T00:00:00+00:00[UTC]junk",
+ "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
+ "02020-01-01T00:00Z",
+ "2020-001-01T00:00Z",
+ "2020-01-001T00:00Z",
+ "2020-01-01T001Z",
+ "2020-01-01T01:001Z",
+ "2020-01-01T01:01:001Z",
+ // valid, but forms not supported in Temporal:
+ "2020-W01-1T00:00Z",
+ "2020-001T00:00Z",
+ "+0002020-01-01T00:00Z",
+ // may be valid in other contexts, but insufficient information for Instant:
+ "2020-01",
+ "+002020-01",
+ "01-01",
+ "2020-W01",
+ "P1Y",
+ "-P12Y",
+ "2020-01-01",
+ "2020-01-01T00",
+ "2020-01-01T00:00",
+ "2020-01-01T00:00:00",
+ "2020-01-01T00:00:00.000000000",
+ // valid, but outside the supported range:
+ "-999999-01-01T00:00Z",
+ "+999999-01-01T00:00Z",
+];
+
+const instance = new Temporal.TimeZone("UTC");
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `"${arg}" should not be a valid ISO string for an Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..147399f6e3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-calendar.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..67630022fc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[UTC][UTC]",
+ "1970-01-01T00:00Z[!UTC][UTC]",
+ "1970-01-01T00:00Z[UTC][!UTC]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00Z[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-separators.js
new file mode 100644
index 0000000000..7ab302d033
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-separators.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z", "uppercase T"],
+ ["1970-01-01t00:00Z", "lowercase T"],
+ ["1970-01-01 00:00Z", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetNanosecondsFor(arg);
+
+ assert.sameValue(
+ result,
+ 0,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..9748b0ceb9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-time-zone-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[Asia/Kolkata]", "named, with Z"],
+ ["1970-01-01T00:00Z[!Europe/Vienna]", "named, with Z and !"],
+ ["1970-01-01T00:00Z[+00:00]", "numeric, with Z"],
+ ["1970-01-01T00:00Z[!-02:30]", "numeric, with Z and !"],
+ ["1970-01-01T00:00+00:00[UTC]", "named, with offset"],
+ ["1970-01-01T00:00+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1970-01-01T00:00+00:00[-08:00]", "numeric, with offset"],
+ ["1970-01-01T00:00+00:00[!+01:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetNanosecondsFor(arg);
+
+ assert.sameValue(
+ result,
+ 0,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..f42373402a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-string-unknown-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[foo=bar]", "alone"],
+ ["1970-01-01T00:00Z[UTC][foo=bar]", "with time zone"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1970-01-01T00:00Z[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1970-01-01T00:00Z[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetNanosecondsFor(arg);
+
+ assert.sameValue(
+ result,
+ 0,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-wrong-type.js
new file mode 100644
index 0000000000..23653301fa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ for Instant
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"],
+ [{}, "plain object"],
+ [Temporal.Instant, "Temporal.Instant, object"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === "string" || (typeof arg === "object" && arg !== null) || typeof arg === "function"
+ ? RangeError
+ : TypeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [Temporal.Instant.prototype, "Temporal.Instant.prototype, object"], // fails brand check in toString()
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getOffsetNanosecondsFor(arg), `${description} does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.js
new file mode 100644
index 0000000000..f48f6cc84c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/argument-zoneddatetime.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.timezone.prototype.getoffsetnanosecondsfor
+description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant
+info: |
+ sec-temporal.timezone.prototype.getoffsetnanosecondsfor step 3:
+ 3. Set _instant_ to ? ToTemporalInstant(_instant_).
+ sec-temporal-totemporalinstant step 1.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalInstantFastPath((datetime) => {
+ const timeZone = Temporal.TimeZone.from("UTC");
+ const result = timeZone.getOffsetNanosecondsFor(datetime);
+ assert.sameValue(result, 0, "offset result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/branding.js
new file mode 100644
index 0000000000..f7450dd176
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/branding.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getOffsetNanosecondsFor = Temporal.TimeZone.prototype.getOffsetNanosecondsFor;
+
+assert.sameValue(typeof getOffsetNanosecondsFor, "function");
+
+const args = [new Temporal.Instant(0n)];
+
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(null, args), "null");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(true, args), "true");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply("", args), "empty string");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(1, args), "1");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply({}, args), "plain object");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getOffsetNanosecondsFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/builtin.js
new file mode 100644
index 0000000000..abc493fc9c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/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.timezone.prototype.getoffsetnanosecondsfor
+description: >
+ Tests that Temporal.TimeZone.prototype.getOffsetNanosecondsFor
+ 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.TimeZone.prototype.getOffsetNanosecondsFor),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getOffsetNanosecondsFor),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getOffsetNanosecondsFor),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getOffsetNanosecondsFor.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string-limits.js
new file mode 100644
index 0000000000..e2714c7819
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string-limits.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: String arguments at the limit of the representable range
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const minInstantStrings = [
+ "-271821-04-20T00:00Z",
+ "-271821-04-19T23:00-01:00",
+ "-271821-04-19T00:00:00.000000001-23:59:59.999999999",
+];
+for (const str of minInstantStrings) {
+ assert.sameValue(instance.getOffsetNanosecondsFor(str), 0, `instant string ${str} should be valid`);
+}
+
+const maxInstantStrings = [
+ "+275760-09-13T00:00Z",
+ "+275760-09-13T01:00+01:00",
+ "+275760-09-13T23:59:59.999999999+23:59:59.999999999",
+];
+
+for (const str of maxInstantStrings) {
+ assert.sameValue(instance.getOffsetNanosecondsFor(str), 0, `instant string ${str} should be valid`);
+}
+
+const outOfRangeInstantStrings = [
+ "-271821-04-19T23:59:59.999999999Z",
+ "-271821-04-19T23:00-00:59:59.999999999",
+ "-271821-04-19T00:00:00-23:59:59.999999999",
+ "-271821-04-19T00:00:00-24:00",
+ "+275760-09-13T00:00:00.000000001Z",
+ "+275760-09-13T01:00+00:59:59.999999999",
+ "+275760-09-14T00:00+23:59:59.999999999",
+ "+275760-09-14T00:00+24:00",
+];
+
+for (const str of outOfRangeInstantStrings) {
+ assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), `instant string ${str} should not be valid`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.js
new file mode 100644
index 0000000000..455ea14865
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/instant-string.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.timezone.prototype.getoffsetnanosecondsfor
+description: Conversion of ISO date-time strings to Temporal.Instant instances
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let str = "1970-01-01T00:00";
+assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "bare date-time string is not an instant");
+str = "1970-01-01T00:00[UTC]";
+assert.throws(RangeError, () => instance.getOffsetNanosecondsFor(str), "date-time + IANA annotation is not an instant");
+
+// The following are all valid strings so should not throw:
+
+const valids = [
+ "1970-01-01T00:00Z",
+ "1970-01-01T00:00+01:00",
+ "1970-01-01T00:00Z[UTC]",
+ "1970-01-01T00:00+01:00[UTC]",
+ "1970-01-01T00:00Z[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[Etc/Ignored][u-ca=hebrew]",
+];
+for (const str of valids) {
+ const result = instance.getOffsetNanosecondsFor(str);
+ assert.sameValue(result, 0);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/leap-second.js
new file mode 100644
index 0000000000..1fb52dbb1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/leap-second.js
@@ -0,0 +1,21 @@
+// |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.timezone.prototype.getoffsetnanosecondsfor
+description: Leap second is a valid ISO string for Instant
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60Z";
+const result = instance.getOffsetNanosecondsFor(arg);
+assert.sameValue(
+ result,
+ 0,
+ "leap second is a valid ISO string for Instant"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js
new file mode 100644
index 0000000000..9a9a560997
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor
+description: Temporal.TimeZone.prototype.getOffsetNanosecondsFor.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.TimeZone.prototype.getOffsetNanosecondsFor, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/name.js
new file mode 100644
index 0000000000..83bf240147
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/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.timezone.prototype.getoffsetnanosecondsfor
+description: Temporal.TimeZone.prototype.getOffsetNanosecondsFor.name is "getOffsetNanosecondsFor".
+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.TimeZone.prototype.getOffsetNanosecondsFor, "name", {
+ value: "getOffsetNanosecondsFor",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/not-a-constructor.js
new file mode 100644
index 0000000000..c8dc628507
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/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.timezone.prototype.getoffsetnanosecondsfor
+description: >
+ Temporal.TimeZone.prototype.getOffsetNanosecondsFor 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.TimeZone.prototype.getOffsetNanosecondsFor();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getOffsetNanosecondsFor), false,
+ "isConstructor(Temporal.TimeZone.prototype.getOffsetNanosecondsFor)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js
new file mode 100644
index 0000000000..5a077f9087
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/prop-desc.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getoffsetnanosecondsfor
+description: The "getOffsetNanosecondsFor" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getOffsetNanosecondsFor,
+ "function",
+ "`typeof TimeZone.prototype.getOffsetNanosecondsFor` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/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/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.js
new file mode 100644
index 0000000000..c71e09cdf3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetNanosecondsFor/year-zero.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.timezone.prototype.getoffsetnanosecondsfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-03-30T00:45Z",
+ "-000000-03-30T01:45+01:00",
+ "-000000-03-30T01:45:00+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetNanosecondsFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js
new file mode 100644
index 0000000000..6db17f2203
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-not-absolute-getOffsetNanosecondsFor-override.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getoffsetstringfor
+description: timeZone.getOffsetNanosecondsFor not called when argument cannot be converted to Temporal.Instant
+features: [Temporal]
+---*/
+
+const timeZone = Temporal.TimeZone.from("UTC");
+let called = false;
+timeZone.getOffsetNanosecondsFor = () => called = true;
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(undefined), "undefined");
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(null), "null");
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(true), "boolean");
+assert.throws(RangeError, () => timeZone.getOffsetStringFor(""), "empty string");
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(Symbol()), "Symbol");
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(5), "number");
+assert.throws(TypeError, () => timeZone.getOffsetStringFor(5n), "bigint");
+assert.throws(RangeError, () => timeZone.getOffsetStringFor({}), "plain object");
+assert.sameValue(called, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..b943ca04b0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-calendar-annotation.js
@@ -0,0 +1,33 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[u-ca=iso8601]", "without time zone"],
+ ["1970-01-01T00:00Z[UTC][u-ca=gregory]", "with time zone"],
+ ["1970-01-01T00:00Z[!u-ca=hebrew]", "with ! and no time zone"],
+ ["1970-01-01T00:00Z[UTC][!u-ca=chinese]", "with ! and time zone"],
+ ["1970-01-01T00:00Z[u-ca=discord]", "annotation is ignored"],
+ ["1970-01-01T00:00Z[!u-ca=discord]", "annotation with ! is ignored"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][u-ca=discord]", "two annotations are ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetStringFor(arg);
+
+ assert.sameValue(
+ result,
+ "+00:00",
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..86c1b0beef
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar]",
+ "1970-01-01T00:00Z[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00Z[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..9b40603406
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-date-with-utc-offset.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.timezone.prototype.getoffsetstringfor
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1970-01-01T00Z",
+ "1970-01-01T00Z[UTC]",
+ "1970-01-01T00Z[!UTC]",
+ "1970-01-01T00Z[Europe/Vienna]",
+ "1970-01-01T00+00:00",
+ "1970-01-01T00+00:00[UTC]",
+ "1970-01-01T00+00:00[!UTC]",
+ "1969-12-31T16-08:00[America/Vancouver]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getOffsetStringFor(arg);
+
+ assert.sameValue(
+ result,
+ "+00:00",
+ `"${arg}" is a valid UTC offset with time for Instant`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ `"${arg}" UTC offset without time is not valid for Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-invalid.js
new file mode 100644
index 0000000000..f79f971678
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-invalid.js
@@ -0,0 +1,69 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: >
+ RangeError thrown if an invalid ISO string (or syntactically valid ISO string
+ that is not supported) is used as an Instant
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ // invalid ISO strings:
+ "",
+ "invalid iso8601",
+ "2020-01-00T00:00Z",
+ "2020-01-32T00:00Z",
+ "2020-02-30T00:00Z",
+ "2021-02-29T00:00Z",
+ "2020-00-01T00:00Z",
+ "2020-13-01T00:00Z",
+ "2020-01-01TZ",
+ "2020-01-01T25:00:00Z",
+ "2020-01-01T01:60:00Z",
+ "2020-01-01T01:60:61Z",
+ "2020-01-01T00:00Zjunk",
+ "2020-01-01T00:00:00Zjunk",
+ "2020-01-01T00:00:00.000000000Zjunk",
+ "2020-01-01T00:00:00+00:00junk",
+ "2020-01-01T00:00:00+00:00[UTC]junk",
+ "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
+ "02020-01-01T00:00Z",
+ "2020-001-01T00:00Z",
+ "2020-01-001T00:00Z",
+ "2020-01-01T001Z",
+ "2020-01-01T01:001Z",
+ "2020-01-01T01:01:001Z",
+ // valid, but forms not supported in Temporal:
+ "2020-W01-1T00:00Z",
+ "2020-001T00:00Z",
+ "+0002020-01-01T00:00Z",
+ // may be valid in other contexts, but insufficient information for Instant:
+ "2020-01",
+ "+002020-01",
+ "01-01",
+ "2020-W01",
+ "P1Y",
+ "-P12Y",
+ "2020-01-01",
+ "2020-01-01T00",
+ "2020-01-01T00:00",
+ "2020-01-01T00:00:00",
+ "2020-01-01T00:00:00.000000000",
+ // valid, but outside the supported range:
+ "-999999-01-01T00:00Z",
+ "+999999-01-01T00:00Z",
+];
+
+const instance = new Temporal.TimeZone("UTC");
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ `"${arg}" should not be a valid ISO string for an Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..bfd20cc7bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-calendar.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..a932833b66
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[UTC][UTC]",
+ "1970-01-01T00:00Z[!UTC][UTC]",
+ "1970-01-01T00:00Z[UTC][!UTC]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00Z[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-separators.js
new file mode 100644
index 0000000000..6568bbc3e4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-separators.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z", "uppercase T"],
+ ["1970-01-01t00:00Z", "lowercase T"],
+ ["1970-01-01 00:00Z", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetStringFor(arg);
+
+ assert.sameValue(
+ result,
+ "+00:00",
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..b158b605e6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-time-zone-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[Asia/Kolkata]", "named, with Z"],
+ ["1970-01-01T00:00Z[!Europe/Vienna]", "named, with Z and !"],
+ ["1970-01-01T00:00Z[+00:00]", "numeric, with Z"],
+ ["1970-01-01T00:00Z[!-02:30]", "numeric, with Z and !"],
+ ["1970-01-01T00:00+00:00[UTC]", "named, with offset"],
+ ["1970-01-01T00:00+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1970-01-01T00:00+00:00[-08:00]", "numeric, with offset"],
+ ["1970-01-01T00:00+00:00[!+01:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetStringFor(arg);
+
+ assert.sameValue(
+ result,
+ "+00:00",
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..6903345bba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-string-unknown-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[foo=bar]", "alone"],
+ ["1970-01-01T00:00Z[UTC][foo=bar]", "with time zone"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1970-01-01T00:00Z[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1970-01-01T00:00Z[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getOffsetStringFor(arg);
+
+ assert.sameValue(
+ result,
+ "+00:00",
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-wrong-type.js
new file mode 100644
index 0000000000..d64c058d3c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ for Instant
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"],
+ [{}, "plain object"],
+ [Temporal.Instant, "Temporal.Instant, object"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === "string" || (typeof arg === "object" && arg !== null) || typeof arg === "function"
+ ? RangeError
+ : TypeError,
+ () => instance.getOffsetStringFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [Temporal.Instant.prototype, "Temporal.Instant.prototype, object"], // fails brand check in toString()
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getOffsetStringFor(arg), `${description} does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.js
new file mode 100644
index 0000000000..38ce243810
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/argument-zoneddatetime.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.timezone.prototype.getoffsetstringfor
+description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant
+info: |
+ sec-temporal.timezone.prototype.getoffsetstringfor step 3:
+ 3. Set _instant_ to ? ToTemporalInstant(_instant_).
+ sec-temporal-totemporalinstant step 1.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalInstantFastPath((datetime) => {
+ const timeZone = Temporal.TimeZone.from("UTC");
+ const result = timeZone.getOffsetStringFor(datetime);
+ assert.sameValue(result, "+00:00", "offset result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.js
new file mode 100644
index 0000000000..cf45188e28
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/basic.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.timezone.prototype.getoffsetstringfor
+description: Basic tests for Temporal.TimeZone.prototype.getOffsetStringFor
+features: [BigInt, Temporal]
+---*/
+
+const instant = new Temporal.Instant(0n);
+
+function test(timeZoneIdentifier, expectedOffsetString, description) {
+ const timeZone = new Temporal.TimeZone(timeZoneIdentifier);
+ assert.sameValue(timeZone.getOffsetStringFor(instant), expectedOffsetString, description);
+}
+
+test("UTC", "+00:00", "offset of UTC is +00:00");
+test("+01:00", "+01:00", "positive offset");
+test("-05:00", "-05:00", "negative offset");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/branding.js
new file mode 100644
index 0000000000..404397204f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getOffsetStringFor = Temporal.TimeZone.prototype.getOffsetStringFor;
+
+assert.sameValue(typeof getOffsetStringFor, "function");
+
+const args = [new Temporal.Instant(0n)];
+
+assert.throws(TypeError, () => getOffsetStringFor.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getOffsetStringFor.apply(null, args), "null");
+assert.throws(TypeError, () => getOffsetStringFor.apply(true, args), "true");
+assert.throws(TypeError, () => getOffsetStringFor.apply("", args), "empty string");
+assert.throws(TypeError, () => getOffsetStringFor.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getOffsetStringFor.apply(1, args), "1");
+assert.throws(TypeError, () => getOffsetStringFor.apply({}, args), "plain object");
+assert.throws(TypeError, () => getOffsetStringFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getOffsetStringFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/builtin.js
new file mode 100644
index 0000000000..8f21c1bdac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+description: >
+ Tests that Temporal.TimeZone.prototype.getOffsetStringFor
+ 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.TimeZone.prototype.getOffsetStringFor),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getOffsetStringFor),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getOffsetStringFor),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getOffsetStringFor.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string-limits.js
new file mode 100644
index 0000000000..aa1a319ad6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string-limits.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: String arguments at the limit of the representable range
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const minInstantStrings = [
+ "-271821-04-20T00:00Z",
+ "-271821-04-19T23:00-01:00",
+ "-271821-04-19T00:00:00.000000001-23:59:59.999999999",
+];
+for (const str of minInstantStrings) {
+ assert.sameValue(instance.getOffsetStringFor(str), "+00:00", `instant string ${str} should be valid`);
+}
+
+const maxInstantStrings = [
+ "+275760-09-13T00:00Z",
+ "+275760-09-13T01:00+01:00",
+ "+275760-09-13T23:59:59.999999999+23:59:59.999999999",
+];
+
+for (const str of maxInstantStrings) {
+ assert.sameValue(instance.getOffsetStringFor(str), "+00:00", `instant string ${str} should be valid`);
+}
+
+const outOfRangeInstantStrings = [
+ "-271821-04-19T23:59:59.999999999Z",
+ "-271821-04-19T23:00-00:59:59.999999999",
+ "-271821-04-19T00:00:00-23:59:59.999999999",
+ "-271821-04-19T00:00:00-24:00",
+ "+275760-09-13T00:00:00.000000001Z",
+ "+275760-09-13T01:00+00:59:59.999999999",
+ "+275760-09-14T00:00+23:59:59.999999999",
+ "+275760-09-14T00:00+24:00",
+];
+
+for (const str of outOfRangeInstantStrings) {
+ assert.throws(RangeError, () => instance.getOffsetStringFor(str), `instant string ${str} should not be valid`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.js
new file mode 100644
index 0000000000..7f24d20313
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/instant-string.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.timezone.prototype.getoffsetstringfor
+description: Conversion of ISO date-time strings to Temporal.Instant instances
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let str = "1970-01-01T00:00";
+assert.throws(RangeError, () => instance.getOffsetStringFor(str), "bare date-time string is not an instant");
+str = "1970-01-01T00:00[UTC]";
+assert.throws(RangeError, () => instance.getOffsetStringFor(str), "date-time + IANA annotation is not an instant");
+
+// The following are all valid strings so should not throw:
+
+const valids = [
+ "1970-01-01T00:00Z",
+ "1970-01-01T00:00+01:00",
+ "1970-01-01T00:00Z[UTC]",
+ "1970-01-01T00:00+01:00[UTC]",
+ "1970-01-01T00:00Z[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[Etc/Ignored][u-ca=hebrew]",
+];
+for (const str of valids) {
+ const result = instance.getOffsetStringFor(str);
+ assert.sameValue(result, "+00:00");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/leap-second.js
new file mode 100644
index 0000000000..a7eccfdb9b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/leap-second.js
@@ -0,0 +1,21 @@
+// |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.timezone.prototype.getoffsetstringfor
+description: Leap second is a valid ISO string for Instant
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60Z";
+const result = instance.getOffsetStringFor(arg);
+assert.sameValue(
+ result,
+ "+00:00",
+ "leap second is a valid ISO string for Instant"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js
new file mode 100644
index 0000000000..459d358ba2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getoffsetstringfor
+description: Temporal.TimeZone.prototype.getOffsetStringFor.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.TimeZone.prototype.getOffsetStringFor, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/name.js
new file mode 100644
index 0000000000..2d89db3d8b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+description: Temporal.TimeZone.prototype.getOffsetStringFor.name is "getOffsetStringFor".
+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.TimeZone.prototype.getOffsetStringFor, "name", {
+ value: "getOffsetStringFor",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/not-a-constructor.js
new file mode 100644
index 0000000000..44e9fbc212
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+description: >
+ Temporal.TimeZone.prototype.getOffsetStringFor 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.TimeZone.prototype.getOffsetStringFor();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getOffsetStringFor), false,
+ "isConstructor(Temporal.TimeZone.prototype.getOffsetStringFor)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/prop-desc.js
new file mode 100644
index 0000000000..0e08435c6f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+description: The "getOffsetStringFor" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getOffsetStringFor,
+ "function",
+ "`typeof TimeZone.prototype.getOffsetStringFor` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getOffsetStringFor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-non-integer.js
new file mode 100644
index 0000000000..2adc452075
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(RangeError, () => timeZone.getOffsetStringFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.js
new file mode 100644
index 0000000000..ac0ea2597c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-not-callable.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.timezone.prototype.getoffsetstringfor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ timeZone.getOffsetNanosecondsFor = notCallable;
+ assert.throws(
+ TypeError,
+ () => timeZone.getOffsetStringFor(instant),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-out-of-range.js
new file mode 100644
index 0000000000..3f0d30bc8d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(RangeError, () => timeZone.getOffsetStringFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/timezone-getoffsetnanosecondsfor-wrong-type.js
new file mode 100644
index 0000000000..0085d63704
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/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.timezone.prototype.getoffsetstringfor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(TypeError, () => timeZone.getOffsetStringFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.js
new file mode 100644
index 0000000000..36f2e103e7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getOffsetStringFor/year-zero.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.timezone.prototype.getoffsetstringfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-03-30T00:45Z",
+ "-000000-03-30T01:45+01:00",
+ "-000000-03-30T01:45:00+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getOffsetStringFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.js
new file mode 100644
index 0000000000..debcd5957e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-negative-epochnanoseconds.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.timezone.prototype.getplaindatetimefor
+description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch
+info: |
+ sec-temporal-getisopartsfromepoch step 1:
+ 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>.
+ sec-temporal-builtintimezonegetplaindatetimefor step 2:
+ 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]).
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(-13849764_999_999_999n);
+
+// This code path shows up anywhere we convert an exact time, before the Unix
+// epoch, with nonzero microseconds or nanoseconds, into a wall time.
+
+const instance = new Temporal.TimeZone("UTC");
+const result = instance.getPlainDateTimeFor(instant);
+TemporalHelpers.assertPlainDateTime(result, 1969, 7, "M07", 24, 16, 50, 35, 0, 0, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js
new file mode 100644
index 0000000000..6c88ccfadf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-not-absolute-getOffsetNanosecondsFor-override.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getplaindatetimefor
+description: timeZone.getOffsetNanosecondsFor not called when argument cannot be converted to Temporal.Instant
+features: [Temporal]
+---*/
+
+const timeZone = Temporal.TimeZone.from("UTC");
+let called = false;
+timeZone.getOffsetNanosecondsFor = () => called = true;
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(undefined), "undefined");
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(null), "null");
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(true), "boolean");
+assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(""), "empty string");
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(Symbol()), "Symbol");
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(5), "number");
+assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(5n), "bigint");
+assert.throws(RangeError, () => timeZone.getPlainDateTimeFor({}), "plain object");
+assert.sameValue(called, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-object-tostring.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-object-tostring.js
new file mode 100644
index 0000000000..371979f3b2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-object-tostring.js
@@ -0,0 +1,23 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Object is converted to a string, then to Temporal.Instant
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = {};
+assert.throws(RangeError, () => instance.getPlainDateTimeFor(arg), "[object Object] is not a valid ISO string");
+
+arg.toString = function() {
+ return "1970-01-01T00:00Z";
+};
+const result = instance.getPlainDateTimeFor(arg);
+TemporalHelpers.assertPlainDateTime(result, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "result of toString is interpreted as ISO string");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..2e4e0795d1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-calendar-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[u-ca=iso8601]", "without time zone"],
+ ["1970-01-01T00:00Z[UTC][u-ca=gregory]", "with time zone"],
+ ["1970-01-01T00:00Z[!u-ca=hebrew]", "with ! and no time zone"],
+ ["1970-01-01T00:00Z[UTC][!u-ca=chinese]", "with ! and time zone"],
+ ["1970-01-01T00:00Z[u-ca=discord]", "annotation is ignored"],
+ ["1970-01-01T00:00Z[!u-ca=discord]", "annotation with ! is ignored"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][u-ca=discord]", "two annotations are ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPlainDateTimeFor(arg);
+
+ TemporalHelpers.assertPlainDateTime(
+ result,
+ 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..b2af63f79f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar]",
+ "1970-01-01T00:00Z[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00Z[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..2f5ed3fd9b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-date-with-utc-offset.js
@@ -0,0 +1,53 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1970-01-01T00Z",
+ "1970-01-01T00Z[UTC]",
+ "1970-01-01T00Z[!UTC]",
+ "1970-01-01T00Z[Europe/Vienna]",
+ "1970-01-01T00+00:00",
+ "1970-01-01T00+00:00[UTC]",
+ "1970-01-01T00+00:00[!UTC]",
+ "1969-12-31T16-08:00[America/Vancouver]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getPlainDateTimeFor(arg);
+
+ TemporalHelpers.assertPlainDateTime(
+ result,
+ 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0,
+ `"${arg}" is a valid UTC offset with time for Instant`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `"${arg}" UTC offset without time is not valid for Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-invalid.js
new file mode 100644
index 0000000000..940de774cf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-invalid.js
@@ -0,0 +1,69 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: >
+ RangeError thrown if an invalid ISO string (or syntactically valid ISO string
+ that is not supported) is used as an Instant
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ // invalid ISO strings:
+ "",
+ "invalid iso8601",
+ "2020-01-00T00:00Z",
+ "2020-01-32T00:00Z",
+ "2020-02-30T00:00Z",
+ "2021-02-29T00:00Z",
+ "2020-00-01T00:00Z",
+ "2020-13-01T00:00Z",
+ "2020-01-01TZ",
+ "2020-01-01T25:00:00Z",
+ "2020-01-01T01:60:00Z",
+ "2020-01-01T01:60:61Z",
+ "2020-01-01T00:00Zjunk",
+ "2020-01-01T00:00:00Zjunk",
+ "2020-01-01T00:00:00.000000000Zjunk",
+ "2020-01-01T00:00:00+00:00junk",
+ "2020-01-01T00:00:00+00:00[UTC]junk",
+ "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
+ "02020-01-01T00:00Z",
+ "2020-001-01T00:00Z",
+ "2020-01-001T00:00Z",
+ "2020-01-01T001Z",
+ "2020-01-01T01:001Z",
+ "2020-01-01T01:01:001Z",
+ // valid, but forms not supported in Temporal:
+ "2020-W01-1T00:00Z",
+ "2020-001T00:00Z",
+ "+0002020-01-01T00:00Z",
+ // may be valid in other contexts, but insufficient information for Instant:
+ "2020-01",
+ "+002020-01",
+ "01-01",
+ "2020-W01",
+ "P1Y",
+ "-P12Y",
+ "2020-01-01",
+ "2020-01-01T00",
+ "2020-01-01T00:00",
+ "2020-01-01T00:00:00",
+ "2020-01-01T00:00:00.000000000",
+ // valid, but outside the supported range:
+ "-999999-01-01T00:00Z",
+ "+999999-01-01T00:00Z",
+];
+
+const instance = new Temporal.TimeZone("UTC");
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `"${arg}" should not be a valid ISO string for an Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..795d9d0314
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-calendar.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..6738c47956
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[UTC][UTC]",
+ "1970-01-01T00:00Z[!UTC][UTC]",
+ "1970-01-01T00:00Z[UTC][!UTC]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00Z[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-separators.js
new file mode 100644
index 0000000000..ea443c1a3c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-separators.js
@@ -0,0 +1,30 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Time separator in string argument can vary
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z", "uppercase T"],
+ ["1970-01-01t00:00Z", "lowercase T"],
+ ["1970-01-01 00:00Z", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPlainDateTimeFor(arg);
+
+ TemporalHelpers.assertPlainDateTime(
+ result,
+ 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..15a4408df4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-time-zone-annotation.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.timezone.prototype.getplaindatetimefor
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[Asia/Kolkata]", "named, with Z"],
+ ["1970-01-01T00:00Z[!Europe/Vienna]", "named, with Z and !"],
+ ["1970-01-01T00:00Z[+00:00]", "numeric, with Z"],
+ ["1970-01-01T00:00Z[!-02:30]", "numeric, with Z and !"],
+ ["1970-01-01T00:00+00:00[UTC]", "named, with offset"],
+ ["1970-01-01T00:00+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1970-01-01T00:00+00:00[-08:00]", "numeric, with offset"],
+ ["1970-01-01T00:00+00:00[!+01:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPlainDateTimeFor(arg);
+
+ TemporalHelpers.assertPlainDateTime(
+ result,
+ 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..bf73224e68
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-string-unknown-annotation.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Various forms of unknown annotation
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[foo=bar]", "alone"],
+ ["1970-01-01T00:00Z[UTC][foo=bar]", "with time zone"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1970-01-01T00:00Z[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1970-01-01T00:00Z[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPlainDateTimeFor(arg);
+
+ TemporalHelpers.assertPlainDateTime(
+ result,
+ 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-wrong-type.js
new file mode 100644
index 0000000000..b6c9d6ccb0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ for Instant
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"],
+ [{}, "plain object"],
+ [Temporal.Instant, "Temporal.Instant, object"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === "string" || (typeof arg === "object" && arg !== null) || typeof arg === "function"
+ ? RangeError
+ : TypeError,
+ () => instance.getPlainDateTimeFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [Temporal.Instant.prototype, "Temporal.Instant.prototype, object"], // fails brand check in toString()
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getPlainDateTimeFor(arg), `${description} does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.js
new file mode 100644
index 0000000000..b25c280c9d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/argument-zoneddatetime.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.timezone.prototype.getplaindatetimefor
+description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant
+info: |
+ sec-temporal.timezone.prototype.getplaindatetimefor step 2:
+ 2. Set _instant_ to ? ToTemporalInstant(_instant_).
+ sec-temporal-totemporalinstant step 1.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalInstantFastPath((datetime) => {
+ const timeZone = Temporal.TimeZone.from("UTC");
+ const result = timeZone.getPlainDateTimeFor(datetime);
+ TemporalHelpers.assertPlainDateTime(result, 2001, 9, "M09", 9, 1, 46, 40, 987, 654, 321);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js
new file mode 100644
index 0000000000..12587c4260
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/balance-negative-time-units.js
@@ -0,0 +1,42 @@
+// |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.timezone.prototype.getplaindatetimefor
+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-balanceisodatetime step 1:
+ 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_).
+ sec-temporal-builtintimezonegetplaindatetimefor step 3:
+ 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_).
+ sec-get-temporal.timezone.prototype.getplaindatetimefor step 4:
+ 4. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+// This code path is encountered if the time zone offset is negative and its
+// absolute value in nanoseconds is greater than the nanosecond field of the
+// exact time's epoch parts
+const tz = TemporalHelpers.specificOffsetTimeZone(-2);
+const instant = new Temporal.Instant(1001n);
+
+const pdt = tz.getPlainDateTimeFor(instant);
+
+TemporalHelpers.assertPlainDateTime(pdt, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 999);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/branding.js
new file mode 100644
index 0000000000..f3f7eccc9c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getPlainDateTimeFor = Temporal.TimeZone.prototype.getPlainDateTimeFor;
+
+assert.sameValue(typeof getPlainDateTimeFor, "function");
+
+const args = [new Temporal.Instant(0n)];
+
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(null, args), "null");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(true, args), "true");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply("", args), "empty string");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(1, args), "1");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply({}, args), "plain object");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getPlainDateTimeFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/builtin.js
new file mode 100644
index 0000000000..efcbeaf959
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+description: >
+ Tests that Temporal.TimeZone.prototype.getPlainDateTimeFor
+ 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.TimeZone.prototype.getPlainDateTimeFor),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPlainDateTimeFor),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPlainDateTimeFor),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getPlainDateTimeFor.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-case-insensitive.js
new file mode 100644
index 0000000000..fdfa4a39ba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-case-insensitive.js
@@ -0,0 +1,17 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Calendar names are case-insensitive
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "iSo8601";
+const result = instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg);
+assert.sameValue(result.calendarId, "iso8601", "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-number.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-number.js
new file mode 100644
index 0000000000..0cf2bc2a3b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-number.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: A number is not allowed to be a calendar
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const numbers = [
+ 1,
+ -19761118,
+ 19761118,
+ 1234567890,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg),
+ "A number is not a valid ISO string for Calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string-leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string-leap-second.js
new file mode 100644
index 0000000000..9b3aeeb9d7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string-leap-second.js
@@ -0,0 +1,21 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Leap second is a valid ISO string for Calendar
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60";
+const result = instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg);
+assert.sameValue(
+ result.calendarId,
+ "iso8601",
+ "leap second is a valid ISO string for Calendar"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string.js
new file mode 100644
index 0000000000..eb154757a6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-string.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.timezone.prototype.getplaindatetimefor
+description: A calendar ID is valid input for Calendar
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "iso8601";
+
+const result = instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg);
+assert.sameValue(result.getISOFields().calendar, "iso8601", `Calendar created from string "${arg}"`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js
new file mode 100644
index 0000000000..295ea57cfb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-temporal-object.js
@@ -0,0 +1,42 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
+info: |
+ sec-temporal-totemporalcalendar step 1.b:
+ b. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return _temporalCalendarLike_.[[Calendar]].
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const plainDate = new Temporal.PlainDate(2000, 5, 2);
+const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const plainMonthDay = new Temporal.PlainMonthDay(5, 2);
+const plainYearMonth = new Temporal.PlainYearMonth(2000, 5);
+const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+
+[plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((arg) => {
+ const actual = [];
+ const expected = [];
+
+ const calendar = arg.getISOFields().calendar;
+
+ Object.defineProperty(arg, "calendar", {
+ get() {
+ actual.push("get calendar");
+ return calendar;
+ },
+ });
+
+ const instance = new Temporal.TimeZone("UTC");
+ const result = instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg);
+ assert.sameValue(result.getISOFields().calendar, calendar, "Temporal object coerced to calendar");
+
+ assert.compareArray(actual, expected, "calendar getter not called");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js
new file mode 100644
index 0000000000..6041c710d6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-undefined.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getplaindatetimefor
+description: Calendar argument defaults to the built-in ISO 8601 calendar
+features: [Temporal]
+---*/
+
+const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z");
+const timeZone = Temporal.TimeZone.from("UTC");
+
+Object.defineProperty(Temporal.Calendar, "from", {
+ get() {
+ throw new Test262Error("Should not call Calendar.from");
+ },
+});
+
+const result1 = timeZone.getPlainDateTimeFor(instant);
+assert.sameValue(result1.calendarId, "iso8601");
+
+const result2 = timeZone.getPlainDateTimeFor(instant, undefined);
+assert.sameValue(result2.calendarId, "iso8601");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-wrong-type.js
new file mode 100644
index 0000000000..9998c731b9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/calendar-wrong-type.js
@@ -0,0 +1,42 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or object for Calendar
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [1n, "bigint"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === 'string' ? RangeError : TypeError,
+ () => instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object that doesn't implement the protocol"],
+ [new Temporal.TimeZone("UTC"), "time zone instance"],
+ [Temporal.Calendar, "Temporal.Calendar, object"],
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getPlainDateTimeFor(new Temporal.Instant(0n), arg), `${description} is not a valid object and does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js
new file mode 100644
index 0000000000..b7844462a5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/custom-timezone.js
@@ -0,0 +1,30 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getplaindatetimefor
+description: getOffsetNanosecondsFor is called by getPlainDateTimeFor
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const actual = [];
+const expected = [
+ "get getOffsetNanosecondsFor",
+ "call timeZone.getOffsetNanosecondsFor",
+];
+
+const instant = Temporal.Instant.from("1975-02-02T14:25:36.123456789Z");
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.observeProperty(actual, timeZone, "getOffsetNanosecondsFor", function (instantArg) {
+ actual.push("call timeZone.getOffsetNanosecondsFor");
+ assert.sameValue(instantArg, instant);
+ return 9876543210123;
+});
+
+const result = timeZone.getPlainDateTimeFor(instant);
+TemporalHelpers.assertPlainDateTime(result, 1975, 2, "M02", 2, 17, 10, 12, 666, 666, 912);
+assert.compareArray(actual, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-limits.js
new file mode 100644
index 0000000000..e57fef37f1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-limits.js
@@ -0,0 +1,48 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: String arguments at the limit of the representable range
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const minInstantStrings = [
+ "-271821-04-20T00:00Z",
+ "-271821-04-19T23:00-01:00",
+ "-271821-04-19T00:00:00.000000001-23:59:59.999999999",
+];
+for (const str of minInstantStrings) {
+ TemporalHelpers.assertPlainDateTime(instance.getPlainDateTimeFor(str), -271821, 4, "M04", 20, 0, 0, 0, 0, 0, 0, `instant string ${str} should be valid`);
+}
+
+const maxInstantStrings = [
+ "+275760-09-13T00:00Z",
+ "+275760-09-13T01:00+01:00",
+ "+275760-09-13T23:59:59.999999999+23:59:59.999999999",
+];
+
+for (const str of maxInstantStrings) {
+ TemporalHelpers.assertPlainDateTime(instance.getPlainDateTimeFor(str), 275760, 9, "M09", 13, 0, 0, 0, 0, 0, 0, `instant string ${str} should be valid`);
+}
+
+const outOfRangeInstantStrings = [
+ "-271821-04-19T23:59:59.999999999Z",
+ "-271821-04-19T23:00-00:59:59.999999999",
+ "-271821-04-19T00:00:00-23:59:59.999999999",
+ "-271821-04-19T00:00:00-24:00",
+ "+275760-09-13T00:00:00.000000001Z",
+ "+275760-09-13T01:00+00:59:59.999999999",
+ "+275760-09-14T00:00+23:59:59.999999999",
+ "+275760-09-14T00:00+24:00",
+];
+
+for (const str of outOfRangeInstantStrings) {
+ assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), `instant string ${str} should not be valid`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.js
new file mode 100644
index 0000000000..b4a9db98e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-multiple-offsets.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.timezone.prototype.getplaindatetimefor
+description: Instant strings with UTC offset fractional part are not confused with time fractional part
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+const str = "1970-01-01T00:02:00.000000000+00:02[+01:30]";
+
+const result = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "UTC offset determined from offset part of string");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-sub-minute-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-sub-minute-offset.js
new file mode 100644
index 0000000000..3e1cf18982
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string-sub-minute-offset.js
@@ -0,0 +1,68 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Temporal.Instant string with sub-minute offset
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const str = "1970-01-01T00:19:32.37+00:19:32.37";
+const result = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "if present, sub-minute offset is accepted exactly");
+
+[
+ "2021-08-19T17:30-07:00:01[-07:00:01]",
+ "2021-08-19T17:30-07:00:00[-07:00:00]",
+ "2021-08-19T17:30-07:00:00.1[-07:00:00.1]",
+ "2021-08-19T17:30-07:00:00.0[-07:00:00.0]",
+ "2021-08-19T17:30-07:00:00.01[-07:00:00.01]",
+ "2021-08-19T17:30-07:00:00.00[-07:00:00.00]",
+ "2021-08-19T17:30-07:00:00.001[-07:00:00.001]",
+ "2021-08-19T17:30-07:00:00.000[-07:00:00.000]",
+ "2021-08-19T17:30-07:00:00.0001[-07:00:00.0001]",
+ "2021-08-19T17:30-07:00:00.0000[-07:00:00.0000]",
+ "2021-08-19T17:30-07:00:00.00001[-07:00:00.00001]",
+ "2021-08-19T17:30-07:00:00.00000[-07:00:00.00000]",
+ "2021-08-19T17:30-07:00:00.000001[-07:00:00.000001]",
+ "2021-08-19T17:30-07:00:00.000000[-07:00:00.000000]",
+ "2021-08-19T17:30-07:00:00.0000001[-07:00:00.0000001]",
+ "2021-08-19T17:30-07:00:00.0000000[-07:00:00.0000000]",
+ "2021-08-19T17:30-07:00:00.00000001[-07:00:00.00000001]",
+ "2021-08-19T17:30-07:00:00.00000000[-07:00:00.00000000]",
+ "2021-08-19T17:30-07:00:00.000000001[-07:00:00.000000001]",
+ "2021-08-19T17:30-07:00:00.000000000[-07:00:00.000000000]",
+
+ "2021-08-19T17:30-07:00:01[-070001]",
+ "2021-08-19T17:30-07:00:00[-070000]",
+ "2021-08-19T17:30-07:00:00.1[-070000.1]",
+ "2021-08-19T17:30-07:00:00.0[-070000.0]",
+ "2021-08-19T17:30-07:00:00.01[-070000.01]",
+ "2021-08-19T17:30-07:00:00.00[-070000.00]",
+ "2021-08-19T17:30-07:00:00.001[-070000.001]",
+ "2021-08-19T17:30-07:00:00.000[-070000.000]",
+ "2021-08-19T17:30-07:00:00.0001[-070000.0001]",
+ "2021-08-19T17:30-07:00:00.0000[-070000.0000]",
+ "2021-08-19T17:30-07:00:00.00001[-070000.00001]",
+ "2021-08-19T17:30-07:00:00.00000[-070000.00000]",
+ "2021-08-19T17:30-07:00:00.000001[-070000.000001]",
+ "2021-08-19T17:30-07:00:00.000000[-070000.000000]",
+ "2021-08-19T17:30-07:00:00.0000001[-070000.0000001]",
+ "2021-08-19T17:30-07:00:00.0000000[-070000.0000000]",
+ "2021-08-19T17:30-07:00:00.00000001[-070000.00000001]",
+ "2021-08-19T17:30-07:00:00.00000000[-070000.00000000]",
+ "2021-08-19T17:30-07:00:00.000000001[-070000.000000001]",
+ "2021-08-19T17:30-07:00:00.000000000[-070000.000000000]"
+].forEach((str) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(str),
+ `ISO strings cannot have sub-minute offsets in time zone annotations: ${str}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js
new file mode 100644
index 0000000000..3f1abf2108
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/instant-string.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Conversion of ISO date-time strings to Temporal.Instant instances
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let str = "1970-01-01T00:00";
+assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "bare date-time string is not an instant");
+str = "1970-01-01T00:00[UTC]";
+assert.throws(RangeError, () => instance.getPlainDateTimeFor(str), "date-time + IANA annotation is not an instant");
+
+str = "1970-01-01T00:00Z";
+const result1 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result1, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "date-time + Z preserves exact time");
+
+str = "1970-01-01T00:00+01:00";
+const result2 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result2, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset preserves exact time with offset");
+
+str = "1970-01-01T00:00Z[Etc/Ignored]";
+const result3 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result3, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation ignores the IANA annotation");
+
+str = "1970-01-01T00:00+01:00[Etc/Ignored]";
+const result4 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result4, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation ignores the IANA annotation");
+
+str = "1970-01-01T00:00Z[u-ca=hebrew]";
+const result6 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result6, 1970, 1, "M01", 1, 0, 0, 0, 0, 0, 0, "date-time + Z + Calendar ignores the Calendar");
+
+str = "1970-01-01T00:00+01:00[u-ca=hebrew]";
+const result5 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result5, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset + Calendar ignores the Calendar");
+
+str = "1970-01-01T00:00+01:00[Etc/Ignored][u-ca=hebrew]";
+const result7 = instance.getPlainDateTimeFor(str);
+TemporalHelpers.assertPlainDateTime(result7, 1969, 12, "M12", 31, 23, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation + Calendar ignores the Calendar and IANA annotation");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/leap-second.js
new file mode 100644
index 0000000000..446e96c161
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/leap-second.js
@@ -0,0 +1,22 @@
+// |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.timezone.prototype.getplaindatetimefor
+description: Leap second is a valid ISO string for Instant
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60Z";
+const result = instance.getPlainDateTimeFor(arg);
+TemporalHelpers.assertPlainDateTime(
+ result,
+ 2016, 12, "M12", 31, 23, 59, 59, 0, 0, 0,
+ "leap second is a valid ISO string for Instant"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js
new file mode 100644
index 0000000000..b3021c4bc7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getplaindatetimefor
+description: Temporal.TimeZone.prototype.getPlainDateTimeFor.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.TimeZone.prototype.getPlainDateTimeFor, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/limits.js
new file mode 100644
index 0000000000..f4cf0af7af
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/limits.js
@@ -0,0 +1,29 @@
+// |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.plaindatetime.prototype.getplaindatetimefor
+description: Checking limits of representable PlainDateTime
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const min = new Temporal.Instant(-8_640_000_000_000_000_000_000n);
+const offsetMin = new Temporal.TimeZone("-23:59");
+const max = new Temporal.Instant(8_640_000_000_000_000_000_000n);
+const offsetMax = new Temporal.TimeZone("+23:59");
+
+TemporalHelpers.assertPlainDateTime(
+ offsetMin.getPlainDateTimeFor(min, "iso8601"),
+ -271821, 4, "M04", 19, 0, 1, 0, 0, 0, 0,
+ "converting from Instant (negative case)"
+);
+
+TemporalHelpers.assertPlainDateTime(
+ offsetMax.getPlainDateTimeFor(max, "iso8601"),
+ 275760, 9, "M09", 13, 23, 59, 0, 0, 0, 0,
+ "converting from Instant (positive case)"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/name.js
new file mode 100644
index 0000000000..abf3dbe263
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+description: Temporal.TimeZone.prototype.getPlainDateTimeFor.name is "getPlainDateTimeFor".
+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.TimeZone.prototype.getPlainDateTimeFor, "name", {
+ value: "getPlainDateTimeFor",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/not-a-constructor.js
new file mode 100644
index 0000000000..2d75ed6e0f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+description: >
+ Temporal.TimeZone.prototype.getPlainDateTimeFor 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.TimeZone.prototype.getPlainDateTimeFor();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPlainDateTimeFor), false,
+ "isConstructor(Temporal.TimeZone.prototype.getPlainDateTimeFor)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js
new file mode 100644
index 0000000000..97cd406175
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/pre-epoch.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getplaindatetimefor
+description: Test of basic functionality for an exact time earlier than the Unix epoch
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instant = Temporal.Instant.from("1969-07-16T13:32:01.234567891Z");
+assert.sameValue(instant.toString(), "1969-07-16T13:32:01.234567891Z");
+const timeZone = Temporal.TimeZone.from("-04:00");
+const dateTime = timeZone.getPlainDateTimeFor(instant);
+TemporalHelpers.assertPlainDateTime(dateTime, 1969, 7, "M07", 16, 9, 32, 1, 234, 567, 891);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/prop-desc.js
new file mode 100644
index 0000000000..b7ec44a682
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+description: The "getPlainDateTimeFor" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getPlainDateTimeFor,
+ "function",
+ "`typeof TimeZone.prototype.getPlainDateTimeFor` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getPlainDateTimeFor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-non-integer.js
new file mode 100644
index 0000000000..29518fb241
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.js
new file mode 100644
index 0000000000..f3608d2f51
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-not-callable.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.timezone.prototype.getplaindatetimefor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ timeZone.getOffsetNanosecondsFor = notCallable;
+ assert.throws(
+ TypeError,
+ () => timeZone.getPlainDateTimeFor(instant),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-out-of-range.js
new file mode 100644
index 0000000000..56ce2f31e6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(RangeError, () => timeZone.getPlainDateTimeFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/timezone-getoffsetnanosecondsfor-wrong-type.js
new file mode 100644
index 0000000000..1976e19cd0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/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.timezone.prototype.getplaindatetimefor
+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 instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+ assert.throws(TypeError, () => timeZone.getPlainDateTimeFor(instant));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.js
new file mode 100644
index 0000000000..56c08eb631
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPlainDateTimeFor/year-zero.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.timezone.prototype.getplaindatetimefor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-03-30T00:45Z",
+ "-000000-03-30T01:45+01:00",
+ "-000000-03-30T01:45:00+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPlainDateTimeFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..13b01796cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-builtin-calendar-no-array-iteration.js
@@ -0,0 +1,24 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Calling the method with a property bag argument 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.TimeZone("UTC");
+const arg = { year: 2000, month: 5, day: 2, hour: 21, minute: 43, second: 5, calendar: "iso8601" };
+instance.getPossibleInstantsFor(arg);
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js
new file mode 100644
index 0000000000..6886ee6617
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-not-datetime.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getpossibleinstantsfor
+description: Appropriate error thrown when argument cannot be converted to Temporal.PlainDateTime
+features: [Temporal]
+---*/
+
+const timeZone = Temporal.TimeZone.from("UTC");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(undefined), "undefined");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(null), "null");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(true), "boolean");
+assert.throws(RangeError, () => timeZone.getPossibleInstantsFor(""), "empty string");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(Symbol()), "Symbol");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(5), "number");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor(5n), "bigint");
+assert.throws(TypeError, () => timeZone.getPossibleInstantsFor({}), "plain object");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-number.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-number.js
new file mode 100644
index 0000000000..a0002e932b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-number.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: A number cannot be used in place of a Temporal.PlainDateTime
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const numbers = [
+ 1,
+ 19761118,
+ -19761118,
+ 1234567890,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `A number (${arg}) is not a valid ISO string for PlainDateTime`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.js
new file mode 100644
index 0000000000..967fdf7454
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-plaindate.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.plaindatetime.prototype.until
+description: Fast path for converting Temporal.PlainDate to Temporal.PlainDateTime by reading internal slots
+info: |
+ sec-temporal.timezone.prototype.getpossibleinstantsfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.b:
+ b. If _item_ has an [[InitializedTemporalDate]] internal slot, then
+ i. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalPlainDateTimeFastPath((date) => {
+ const timezone = new Temporal.TimeZone("UTC");
+ const result = timezone.getPossibleInstantsFor(date);
+ assert.sameValue(result.length, 1, "one possible instant");
+ assert.sameValue(result[0].epochNanoseconds, 957_225_600_000_000_000n, "epochNanoseconds result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-case-insensitive.js
new file mode 100644
index 0000000000..b83394a8e0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-case-insensitive.js
@@ -0,0 +1,20 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: The calendar name is case-insensitive
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "IsO8601";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getPossibleInstantsFor(arg);
+assert.compareArray(result.map(i => i.epochNanoseconds), [217_123_200_000_000_000n], "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-leap-second.js
new file mode 100644
index 0000000000..9c4175f5da
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-leap-second.js
@@ -0,0 +1,24 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Leap second is a valid ISO string for a calendar in a property bag
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "2016-12-31T23:59:60";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getPossibleInstantsFor(arg);
+assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_123_200_000_000_000n],
+ "leap second is a valid ISO string for calendar"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-number.js
new file mode 100644
index 0000000000..c677cdf355
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-number.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: A number as calendar in a property bag is not accepted
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const numbers = [
+ 1,
+ 19970327,
+ -19970327,
+ 1234567890,
+];
+
+for (const calendar of numbers) {
+ const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+ assert.throws(
+ TypeError,
+ () => instance.getPossibleInstantsFor(arg),
+ "Numbers cannot be used as a calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-string.js
new file mode 100644
index 0000000000..bcccdb578c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-string.js
@@ -0,0 +1,20 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: A calendar ID is valid input for Calendar
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const calendar = "iso8601";
+
+const arg = { year: 1976, monthCode: "M11", day: 18, calendar };
+const result = instance.getPossibleInstantsFor(arg);
+assert.compareArray(result.map(i => i.epochNanoseconds), [217_123_200_000_000_000n], `Calendar created from string "${calendar}"`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-wrong-type.js
new file mode 100644
index 0000000000..9bb67c587e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Appropriate error thrown when a calendar property from a property bag cannot
+ be converted to a calendar object or string
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const timeZone = new Temporal.TimeZone("UTC");
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [1n, "bigint"],
+];
+
+for (const [calendar, description] of primitiveTests) {
+ const arg = { year: 2019, monthCode: "M11", day: 1, calendar };
+ assert.throws(
+ typeof calendar === 'string' ? RangeError : TypeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object that doesn't implement the protocol"],
+ [new Temporal.TimeZone("UTC"), "time zone instance"],
+ [Temporal.Calendar, "Temporal.Calendar, object"],
+ [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields()
+];
+
+for (const [calendar, description] of typeErrorTests) {
+ const arg = { year: 2019, monthCode: "M11", day: 1, calendar };
+ assert.throws(TypeError, () => instance.getPossibleInstantsFor(arg), `${description} is not a valid property bag and does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-year-zero.js
new file mode 100644
index 0000000000..0afcf6f978
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-propertybag-calendar-year-zero.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-10-31",
+ "-000000-10-31T17:45",
+ "-000000-10-31T17:45Z",
+ "-000000-10-31T17:45+01:00",
+ "-000000-10-31T17:45+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..ccc8eb6447
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-calendar-annotation.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[u-ca=iso8601]", "without time zone"],
+ ["1976-11-18T15:23[UTC][u-ca=iso8601]", "with time zone"],
+ ["1976-11-18T15:23[!u-ca=iso8601]", "with ! and no time zone"],
+ ["1976-11-18T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"],
+ ["1976-11-18T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPossibleInstantsFor(arg);
+
+ assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_178_580_000_000_000n],
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..d0d4f3bb3d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00[!foo=bar]",
+ "1970-01-01T00:00[UTC][!foo=bar]",
+ "1970-01-01T00:00[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..a6a045e438
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-date-with-utc-offset.js
@@ -0,0 +1,49 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1976-11-18T15:23+00:00",
+ "1976-11-18T15:23+00:00[UTC]",
+ "1976-11-18T15:23+00:00[!UTC]",
+ "1976-11-18T15:23-02:30[America/St_Johns]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getPossibleInstantsFor(arg);
+
+ assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_178_580_000_000_000n],
+ `"${arg}" is a valid UTC offset with time for PlainDateTime`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `"${arg}" UTC offset without time is not valid for PlainDateTime`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..b29552e4c7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-calendar.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+ "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..8d8944fe22
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00[UTC][UTC]",
+ "1970-01-01T00:00[!UTC][UTC]",
+ "1970-01-01T00:00[UTC][!UTC]",
+ "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-separators.js
new file mode 100644
index 0000000000..d25d8923d1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-separators.js
@@ -0,0 +1,30 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Time separator in string argument can vary
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23", "uppercase T"],
+ ["1976-11-18t15:23", "lowercase T"],
+ ["1976-11-18 15:23", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPossibleInstantsFor(arg);
+
+ assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_178_580_000_000_000n],
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..eba484f410
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-time-zone-annotation.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.timezone.prototype.getpossibleinstantsfor
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[Asia/Kolkata]", "named, with no offset"],
+ ["1976-11-18T15:23[!Europe/Vienna]", "named, with ! and no offset"],
+ ["1976-11-18T15:23[+00:00]", "numeric, with no offset"],
+ ["1976-11-18T15:23[!-02:30]", "numeric, with ! and no offset"],
+ ["1976-11-18T15:23+00:00[UTC]", "named, with offset"],
+ ["1976-11-18T15:23+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1976-11-18T15:23+00:00[+01:00]", "numeric, with offset"],
+ ["1976-11-18T15:23+00:00[!-08:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPossibleInstantsFor(arg);
+
+ assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_178_580_000_000_000n],
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..df1811ea08
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-unknown-annotation.js
@@ -0,0 +1,32 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Various forms of unknown annotation
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const tests = [
+ ["1976-11-18T15:23[foo=bar]", "alone"],
+ ["1976-11-18T15:23[UTC][foo=bar]", "with time zone"],
+ ["1976-11-18T15:23[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1976-11-18T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1976-11-18T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPossibleInstantsFor(arg);
+
+ assert.compareArray(
+ result.map(i => i.epochNanoseconds),
+ [217_178_580_000_000_000n],
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.js
new file mode 100644
index 0000000000..11ee17ba4e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-string-with-utc-designator.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.timezone.prototype.getpossibleinstantsfor
+description: RangeError thrown if a string with UTC designator is used as a PlainDateTime
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "2019-10-01T09:00:00Z",
+ "2019-10-01T09:00:00Z[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ "String with UTC designator should not be valid as a PlainDateTime"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-wrong-type.js
new file mode 100644
index 0000000000..697d95c314
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-wrong-type.js
@@ -0,0 +1,43 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or property bag for PlainDateTime
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [1n, "bigint"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === 'string' ? RangeError : TypeError,
+ () => instance.getPossibleInstantsFor(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object"],
+ [Temporal.PlainDateTime, "Temporal.PlainDateTime, object"],
+ [Temporal.PlainDateTime.prototype, "Temporal.PlainDateTime.prototype, object"],
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getPossibleInstantsFor(arg), `${description} is not a valid property bag and does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.js
new file mode 100644
index 0000000000..62e3cd227c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-balance-negative-time-units.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.timezone.prototype.getpossibleinstantsfor
+description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime
+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-balanceisodatetime step 1:
+ 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_).
+ sec-temporal-builtintimezonegetplaindatetimefor step 3:
+ 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_).
+ sec-temporal-totemporaldatetime step 3.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ ii. 1. Return ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]).
+ sec-temporal.timezone.prototype.getpossibleinstantsfor step 3:
+ 3. Set _dateTime_ ? ToTemporalDateTime(_dateTime_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+// This code path is encountered if the time zone offset is negative and its
+// absolute value in nanoseconds is greater than the nanosecond field of the
+// exact time's epoch parts
+const tz = TemporalHelpers.specificOffsetTimeZone(-2);
+const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz);
+
+const conversionTimeZone = new Temporal.TimeZone("UTC"); // should not be used to interpret the argument
+const instants = conversionTimeZone.getPossibleInstantsFor(datetime);
+
+assert.sameValue(instants.length, 1);
+assert.sameValue(instants[0].epochNanoseconds, 3661_001_000_999n);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.js
new file mode 100644
index 0000000000..765b0c7115
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-negative-epochnanoseconds.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.timezone.prototype.getpossibleinstantsfor
+description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch
+info: |
+ sec-temporal-getisopartsfromepoch step 1:
+ 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>.
+ sec-temporal-builtintimezonegetplaindatetimefor step 2:
+ 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]).
+features: [Temporal]
+includes: [compareArray.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC");
+
+// This code path shows up anywhere we convert an exact time, before the Unix
+// epoch, with nonzero microseconds or nanoseconds, into a wall time.
+
+const instance = new Temporal.TimeZone("UTC");
+const result = instance.getPossibleInstantsFor(datetime);
+assert.compareArray(result.map((i) => i.epochNanoseconds), [-13849764_999_999_999n]);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
new file mode 100644
index 0000000000..10dabb1e8e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(RangeError, () => builtinTimeZone.getPossibleInstantsFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
new file mode 100644
index 0000000000..3326adae54
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js
@@ -0,0 +1,23 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ timeZone.getOffsetNanosecondsFor = notCallable;
+ assert.throws(
+ TypeError,
+ () => builtinTimeZone.getPossibleInstantsFor(datetime),
+ `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
new file mode 100644
index 0000000000..e84e4bb835
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(RangeError, () => builtinTimeZone.getPossibleInstantsFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js
new file mode 100644
index 0000000000..b892868072
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.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.timezone.prototype.getpossibleinstantsfor
+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);
+ const builtinTimeZone = new Temporal.TimeZone("UTC");
+ assert.throws(TypeError, () => builtinTimeZone.getPossibleInstantsFor(datetime));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/branding.js
new file mode 100644
index 0000000000..28112ebb0b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/branding.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getpossibleinstantsfor
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getPossibleInstantsFor = Temporal.TimeZone.prototype.getPossibleInstantsFor;
+
+assert.sameValue(typeof getPossibleInstantsFor, "function");
+
+const args = [new Temporal.PlainDateTime(2022, 6, 22)];
+
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(null, args), "null");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(true, args), "true");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply("", args), "empty string");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(1, args), "1");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply({}, args), "plain object");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getPossibleInstantsFor.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/builtin.js
new file mode 100644
index 0000000000..2b19200aef
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Tests that Temporal.TimeZone.prototype.getPossibleInstantsFor
+ 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.TimeZone.prototype.getPossibleInstantsFor),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPossibleInstantsFor),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPossibleInstantsFor),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getPossibleInstantsFor.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-datefromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..97dcbe9239
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-datefromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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.TimeZone("UTC");
+const arg = { year: 2000, month: 5, day: 2, calendar };
+instance.getPossibleInstantsFor(arg);
+assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.js
new file mode 100644
index 0000000000..ecbfbceb69
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-fields-iterable.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.timezone.prototype.getpossibleinstantsfor
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.timezone.prototype.getpossibleinstantsfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.c:
+ c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"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 timeZone = new Temporal.TimeZone("UTC");
+timeZone.getPossibleInstantsFor({ year: 2000, month: 5, day: 2, calendar });
+
+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/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.js
new file mode 100644
index 0000000000..32b8613628
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/calendar-temporal-object.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.timezone.prototype.getpossibleinstantsfor
+description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
+info: |
+ sec-temporal.timezone.prototype.getpossibleinstantsfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.c:
+ c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ sec-temporal-gettemporalcalendarwithisodefault step 2:
+ 2. Return ? ToTemporalCalendarWithISODefault(_calendar_).
+ sec-temporal-totemporalcalendarwithisodefault step 2:
+ 3. Return ? ToTemporalCalendar(_temporalCalendarLike_).
+ sec-temporal-totemporalcalendar step 1.a:
+ a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return _temporalCalendarLike_.[[Calendar]].
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => {
+ const timeZone = new Temporal.TimeZone("UTC");
+ timeZone.getPossibleInstantsFor({ year: 2000, month: 5, day: 2, calendar: temporalObject });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..245f90b226
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/constructor-in-calendar-fields.js
@@ -0,0 +1,17 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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 arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar};
+const instance = new Temporal.TimeZone("UTC");
+
+assert.throws(RangeError, () => instance.getPossibleInstantsFor(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..30d79e324c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/duplicate-calendar-fields.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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'], ['day'], ['hour'], ['microsecond'], ['millisecond'], ['minute'], ['month'], ['monthCode'], ['nanosecond'], ['second'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar };
+ const instance = new Temporal.TimeZone("UTC");
+
+ assert.throws(RangeError, () => instance.getPossibleInstantsFor(arg));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/fixed-offset-near-date-time-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/fixed-offset-near-date-time-limits.js
new file mode 100644
index 0000000000..bf70291dc9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/fixed-offset-near-date-time-limits.js
@@ -0,0 +1,57 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Call getPossibleInstantsFor with values near the date/time limit and a fixed offset.
+features: [Temporal, exponentiation]
+---*/
+
+const oneHour = 1n * 60n * 60n * 1000n**3n;
+
+const minDt = new Temporal.PlainDateTime(-271821, 4, 19, 1, 0, 0, 0, 0, 0);
+const minValidDt = new Temporal.PlainDateTime(-271821, 4, 20, 0, 0, 0, 0, 0, 0);
+const maxDt = new Temporal.PlainDateTime(275760, 9, 13, 0, 0, 0, 0, 0, 0);
+
+let zero = new Temporal.TimeZone("+00");
+let plusOne = new Temporal.TimeZone("+01");
+let minusOne = new Temporal.TimeZone("-01");
+
+// Try the minimum date-time.
+assert.throws(RangeError, () => zero.getPossibleInstantsFor(minDt));
+assert.throws(RangeError, () => plusOne.getPossibleInstantsFor(minDt));
+assert.throws(RangeError, () => minusOne.getPossibleInstantsFor(minDt));
+
+// Try the minimum valid date-time.
+{
+ let r = zero.getPossibleInstantsFor(minValidDt);
+ assert.sameValue(r.length, 1);
+ assert.sameValue(r[0].epochNanoseconds, -86_40000_00000_00000_00000n);
+}
+
+{
+ let r = minusOne.getPossibleInstantsFor(minValidDt);
+ assert.sameValue(r.length, 1);
+ assert.sameValue(r[0].epochNanoseconds, -86_40000_00000_00000_00000n + oneHour);
+}
+
+assert.throws(RangeError, () => plusOne.getPossibleInstantsFor(minValidDt));
+
+// Try the maximum valid date-time.
+{
+ let r = zero.getPossibleInstantsFor(maxDt);
+ assert.sameValue(r.length, 1);
+ assert.sameValue(r[0].epochNanoseconds, 86_40000_00000_00000_00000n);
+}
+
+{
+ let r = plusOne.getPossibleInstantsFor(maxDt);
+ assert.sameValue(r.length, 1);
+ assert.sameValue(r[0].epochNanoseconds, 86_40000_00000_00000_00000n - oneHour);
+}
+
+assert.throws(RangeError, () => minusOne.getPossibleInstantsFor(maxDt));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..d40ebce61e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/infinity-throws-rangeerror.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.
+
+/*---
+description: Throws if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.timezone.prototype.getpossibleinstantsfor
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 };
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => {
+ assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
+ assert.throws(RangeError, () => instance.getPossibleInstantsFor({ ...base, [prop]: obj }));
+ 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/TimeZone/prototype/getPossibleInstantsFor/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/leap-second.js
new file mode 100644
index 0000000000..6b96daa289
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/leap-second.js
@@ -0,0 +1,30 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+description: Leap second is a valid ISO string for PlainDateTime
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let arg = "2016-12-31T23:59:60";
+const result1 = instance.getPossibleInstantsFor(arg);
+assert.compareArray(
+ result1.map(i => i.epochNanoseconds),
+ [1_483_228_799_000_000_000n],
+ "leap second is a valid ISO string for PlainDateTime"
+);
+
+arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
+const result2 = instance.getPossibleInstantsFor(arg);
+assert.compareArray(
+ result2.map(i => i.epochNanoseconds),
+ [1_483_228_799_000_000_000n],
+ "second: 60 is ignored in property bag for PlainDateTime"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js
new file mode 100644
index 0000000000..cc04a14788
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getpossibleinstantsfor
+description: Temporal.TimeZone.prototype.getPossibleInstantsFor.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.TimeZone.prototype.getPossibleInstantsFor, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/name.js
new file mode 100644
index 0000000000..f5713a2e80
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/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.timezone.prototype.getpossibleinstantsfor
+description: Temporal.TimeZone.prototype.getPossibleInstantsFor.name is "getPossibleInstantsFor".
+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.TimeZone.prototype.getPossibleInstantsFor, "name", {
+ value: "getPossibleInstantsFor",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/not-a-constructor.js
new file mode 100644
index 0000000000..14789fdf50
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/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.timezone.prototype.getpossibleinstantsfor
+description: >
+ Temporal.TimeZone.prototype.getPossibleInstantsFor 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.TimeZone.prototype.getPossibleInstantsFor();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPossibleInstantsFor), false,
+ "isConstructor(Temporal.TimeZone.prototype.getPossibleInstantsFor)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js
new file mode 100644
index 0000000000..aeb6aa976e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/prop-desc.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getpossibleinstantsfor
+description: The "getPossibleInstantsFor" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getPossibleInstantsFor,
+ "function",
+ "`typeof TimeZone.prototype.getPossibleInstantsFor` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..09aeb655a2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/proto-in-calendar-fields.js
@@ -0,0 +1,17 @@
+// |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.timezone.prototype.getpossibleinstantsfor
+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 arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar};
+const instance = new Temporal.TimeZone("UTC");
+
+assert.throws(RangeError, () => instance.getPossibleInstantsFor(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.js
new file mode 100644
index 0000000000..e75ccfd8cf
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/read-time-fields-before-datefromfields.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.timezone.prototype.getpossibleinstantsfor
+description: The time fields are read from the object before being passed to dateFromFields().
+info: |
+ sec-temporal.timezone.prototype.getpossibleinstantsfor step 3:
+ 3. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
+ sec-temporal-totemporaldatetime step 2.e:
+ e. Let _result_ 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 timezone = new Temporal.TimeZone("UTC");
+const calendar = TemporalHelpers.calendarMakeInfinityTime();
+const result = timezone.getPossibleInstantsFor({ year: 1970, month: 1, day: 1, calendar });
+
+assert.sameValue(result.length, 1, "result array length");
+assert.sameValue(result[0].epochNanoseconds, 0n, "epochNanoseconds result");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/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/TimeZone/prototype/getPossibleInstantsFor/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.js
new file mode 100644
index 0000000000..fa4c15dce1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPossibleInstantsFor/year-zero.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.timezone.prototype.getpossibleinstantsfor
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-12-07",
+ "-000000-12-07T03:24:30",
+ "-000000-12-07T03:24:30+01:00",
+ "-000000-12-07T03:24:30+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPossibleInstantsFor(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..b8867e8b6a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-calendar-annotation.js
@@ -0,0 +1,33 @@
+// |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.timezone.prototype.getprevioustransition
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[u-ca=iso8601]", "without time zone"],
+ ["1970-01-01T00:00Z[UTC][u-ca=gregory]", "with time zone"],
+ ["1970-01-01T00:00Z[!u-ca=hebrew]", "with ! and no time zone"],
+ ["1970-01-01T00:00Z[UTC][!u-ca=chinese]", "with ! and time zone"],
+ ["1970-01-01T00:00Z[u-ca=discord]", "annotation is ignored"],
+ ["1970-01-01T00:00Z[!u-ca=discord]", "annotation with ! is ignored"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][u-ca=discord]", "two annotations are ignored"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPreviousTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..7476dd322d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-critical-unknown-annotation.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getprevioustransition
+description: Unknown annotations with critical flag are rejected
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar]",
+ "1970-01-01T00:00Z[u-ca=iso8601][!foo=bar]",
+ "1970-01-01T00:00Z[UTC][!foo=bar][u-ca=iso8601]",
+ "1970-01-01T00:00Z[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..f8c6ed644e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-date-with-utc-offset.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.timezone.prototype.getprevioustransition
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const validStrings = [
+ "1970-01-01T00Z",
+ "1970-01-01T00Z[UTC]",
+ "1970-01-01T00Z[!UTC]",
+ "1970-01-01T00Z[Europe/Vienna]",
+ "1970-01-01T00+00:00",
+ "1970-01-01T00+00:00[UTC]",
+ "1970-01-01T00+00:00[!UTC]",
+ "1969-12-31T16-08:00[America/Vancouver]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.getPreviousTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `"${arg}" is a valid UTC offset with time for Instant`
+ );
+}
+
+const invalidStrings = [
+ "2022-09-15Z",
+ "2022-09-15Z[UTC]",
+ "2022-09-15Z[Europe/Vienna]",
+ "2022-09-15+00:00",
+ "2022-09-15+00:00[UTC]",
+ "2022-09-15-02:30",
+ "2022-09-15-02:30[America/St_Johns]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ `"${arg}" UTC offset without time is not valid for Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-invalid.js
new file mode 100644
index 0000000000..56b970b203
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-invalid.js
@@ -0,0 +1,69 @@
+// |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.timezone.prototype.getprevioustransition
+description: >
+ RangeError thrown if an invalid ISO string (or syntactically valid ISO string
+ that is not supported) is used as an Instant
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ // invalid ISO strings:
+ "",
+ "invalid iso8601",
+ "2020-01-00T00:00Z",
+ "2020-01-32T00:00Z",
+ "2020-02-30T00:00Z",
+ "2021-02-29T00:00Z",
+ "2020-00-01T00:00Z",
+ "2020-13-01T00:00Z",
+ "2020-01-01TZ",
+ "2020-01-01T25:00:00Z",
+ "2020-01-01T01:60:00Z",
+ "2020-01-01T01:60:61Z",
+ "2020-01-01T00:00Zjunk",
+ "2020-01-01T00:00:00Zjunk",
+ "2020-01-01T00:00:00.000000000Zjunk",
+ "2020-01-01T00:00:00+00:00junk",
+ "2020-01-01T00:00:00+00:00[UTC]junk",
+ "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk",
+ "02020-01-01T00:00Z",
+ "2020-001-01T00:00Z",
+ "2020-01-001T00:00Z",
+ "2020-01-01T001Z",
+ "2020-01-01T01:001Z",
+ "2020-01-01T01:01:001Z",
+ // valid, but forms not supported in Temporal:
+ "2020-W01-1T00:00Z",
+ "2020-001T00:00Z",
+ "+0002020-01-01T00:00Z",
+ // may be valid in other contexts, but insufficient information for Instant:
+ "2020-01",
+ "+002020-01",
+ "01-01",
+ "2020-W01",
+ "P1Y",
+ "-P12Y",
+ "2020-01-01",
+ "2020-01-01T00",
+ "2020-01-01T00:00",
+ "2020-01-01T00:00:00",
+ "2020-01-01T00:00:00.000000000",
+ // valid, but outside the supported range:
+ "-999999-01-01T00:00Z",
+ "+999999-01-01T00:00Z",
+];
+
+const instance = new Temporal.TimeZone("UTC");
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ `"${arg}" should not be a valid ISO string for an Instant`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..9aef6ab2a8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-calendar.js
@@ -0,0 +1,28 @@
+// |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.timezone.prototype.getprevioustransition
+description: >
+ More than one calendar annotation is not syntactical if any have the criical
+ flag
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[!u-ca=iso8601][u-ca=iso8601]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][!u-ca=iso8601]",
+ "1970-01-01T00:00Z[u-ca=iso8601][foo=bar][!u-ca=iso8601]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..2903f9d7e2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-multiple-time-zone.js
@@ -0,0 +1,27 @@
+// |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.timezone.prototype.getprevioustransition
+description: More than one time zone annotation is not syntactical
+features: [Temporal]
+---*/
+
+const invalidStrings = [
+ "1970-01-01T00:00Z[UTC][UTC]",
+ "1970-01-01T00:00Z[!UTC][UTC]",
+ "1970-01-01T00:00Z[UTC][!UTC]",
+ "1970-01-01T00:00Z[UTC][u-ca=iso8601][UTC]",
+ "1970-01-01T00:00Z[UTC][foo=bar][UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-separators.js
new file mode 100644
index 0000000000..8e6d11d103
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-separators.js
@@ -0,0 +1,29 @@
+// |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.timezone.prototype.getprevioustransition
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z", "uppercase T"],
+ ["1970-01-01t00:00Z", "lowercase T"],
+ ["1970-01-01 00:00Z", "space between date and time"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPreviousTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..fe3c987a08
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-time-zone-annotation.js
@@ -0,0 +1,34 @@
+// |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.timezone.prototype.getprevioustransition
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[Asia/Kolkata]", "named, with Z"],
+ ["1970-01-01T00:00Z[!Europe/Vienna]", "named, with Z and !"],
+ ["1970-01-01T00:00Z[+00:00]", "numeric, with Z"],
+ ["1970-01-01T00:00Z[!-02:30]", "numeric, with Z and !"],
+ ["1970-01-01T00:00+00:00[UTC]", "named, with offset"],
+ ["1970-01-01T00:00+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1970-01-01T00:00+00:00[-08:00]", "numeric, with offset"],
+ ["1970-01-01T00:00+00:00[!+01:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPreviousTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..d998b85a68
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-string-unknown-annotation.js
@@ -0,0 +1,31 @@
+// |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.timezone.prototype.getprevioustransition
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1970-01-01T00:00Z[foo=bar]", "alone"],
+ ["1970-01-01T00:00Z[UTC][foo=bar]", "with time zone"],
+ ["1970-01-01T00:00Z[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1970-01-01T00:00Z[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1970-01-01T00:00Z[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.TimeZone("UTC");
+
+tests.forEach(([arg, description]) => {
+ const result = instance.getPreviousTransition(arg);
+
+ assert.sameValue(
+ result,
+ null,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-wrong-type.js
new file mode 100644
index 0000000000..0519c26435
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-wrong-type.js
@@ -0,0 +1,46 @@
+// |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.timezone.prototype.getprevioustransition
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ for Instant
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const primitiveTests = [
+ [undefined, "undefined"],
+ [null, "null"],
+ [true, "boolean"],
+ ["", "empty string"],
+ [1, "number that doesn't convert to a valid ISO string"],
+ [19761118, "number that would convert to a valid ISO string in other contexts"],
+ [1n, "bigint"],
+ [{}, "plain object"],
+ [Temporal.Instant, "Temporal.Instant, object"],
+];
+
+for (const [arg, description] of primitiveTests) {
+ assert.throws(
+ typeof arg === "string" || (typeof arg === "object" && arg !== null) || typeof arg === "function"
+ ? RangeError
+ : TypeError,
+ () => instance.getPreviousTransition(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [Temporal.Instant.prototype, "Temporal.Instant.prototype, object"], // fails brand check in toString()
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.getPreviousTransition(arg), `${description} does not convert to a string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.js
new file mode 100644
index 0000000000..dcc93e83c5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/argument-zoneddatetime.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.timezone.prototype.getprevioustransition
+description: Fast path for converting Temporal.ZonedDateTime to Temporal.Instant
+info: |
+ sec-temporal.timezone.prototype.getprevioustransition step 3:
+ 3. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
+ sec-temporal-totemporalinstant step 1.b:
+ b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ i. Return ! CreateTemporalInstant(_item_.[[Nanoseconds]]).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkToTemporalInstantFastPath((datetime) => {
+ const timeZone = Temporal.TimeZone.from("UTC");
+ const result = timeZone.getPreviousTransition(datetime);
+ assert.sameValue(result, null, "transition result");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/branding.js
new file mode 100644
index 0000000000..5d8f674b80
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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.timezone.prototype.getprevioustransition
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getPreviousTransition = Temporal.TimeZone.prototype.getPreviousTransition;
+
+assert.sameValue(typeof getPreviousTransition, "function");
+
+const args = [new Temporal.Instant(0n)];
+
+assert.throws(TypeError, () => getPreviousTransition.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => getPreviousTransition.apply(null, args), "null");
+assert.throws(TypeError, () => getPreviousTransition.apply(true, args), "true");
+assert.throws(TypeError, () => getPreviousTransition.apply("", args), "empty string");
+assert.throws(TypeError, () => getPreviousTransition.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => getPreviousTransition.apply(1, args), "1");
+assert.throws(TypeError, () => getPreviousTransition.apply({}, args), "plain object");
+assert.throws(TypeError, () => getPreviousTransition.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
+assert.throws(TypeError, () => getPreviousTransition.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/builtin.js
new file mode 100644
index 0000000000..0051ee5e68
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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.timezone.prototype.getprevioustransition
+description: >
+ Tests that Temporal.TimeZone.prototype.getPreviousTransition
+ 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.TimeZone.prototype.getPreviousTransition),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.getPreviousTransition),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.getPreviousTransition),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.getPreviousTransition.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string-limits.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string-limits.js
new file mode 100644
index 0000000000..7bf8f08e9d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string-limits.js
@@ -0,0 +1,47 @@
+// |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.timezone.prototype.getprevioustransition
+description: String arguments at the limit of the representable range
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const minInstantStrings = [
+ "-271821-04-20T00:00Z",
+ "-271821-04-19T23:00-01:00",
+ "-271821-04-19T00:00:00.000000001-23:59:59.999999999",
+];
+for (const str of minInstantStrings) {
+ assert.sameValue(instance.getPreviousTransition(str), null, `instant string ${str} should be valid`);
+}
+
+const maxInstantStrings = [
+ "+275760-09-13T00:00Z",
+ "+275760-09-13T01:00+01:00",
+ "+275760-09-13T23:59:59.999999999+23:59:59.999999999",
+];
+
+for (const str of maxInstantStrings) {
+ assert.sameValue(instance.getPreviousTransition(str), null, `instant string ${str} should be valid`);
+}
+
+const outOfRangeInstantStrings = [
+ "-271821-04-19T23:59:59.999999999Z",
+ "-271821-04-19T23:00-00:59:59.999999999",
+ "-271821-04-19T00:00:00-23:59:59.999999999",
+ "-271821-04-19T00:00:00-24:00",
+ "+275760-09-13T00:00:00.000000001Z",
+ "+275760-09-13T01:00+00:59:59.999999999",
+ "+275760-09-14T00:00+23:59:59.999999999",
+ "+275760-09-14T00:00+24:00",
+];
+
+for (const str of outOfRangeInstantStrings) {
+ assert.throws(RangeError, () => instance.getPreviousTransition(str), `instant string ${str} should not be valid`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.js
new file mode 100644
index 0000000000..1b29755e93
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/instant-string.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.timezone.prototype.getprevioustransition
+description: Conversion of ISO date-time strings to Temporal.Instant instances
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+let str = "1970-01-01T00:00";
+assert.throws(RangeError, () => instance.getPreviousTransition(str), "bare date-time string is not an instant");
+str = "1970-01-01T00:00[UTC]";
+assert.throws(RangeError, () => instance.getPreviousTransition(str), "date-time + IANA annotation is not an instant");
+
+// The following are all valid strings so should not throw:
+
+const valids = [
+ "1970-01-01T00:00Z",
+ "1970-01-01T00:00+01:00",
+ "1970-01-01T00:00Z[UTC]",
+ "1970-01-01T00:00+01:00[UTC]",
+ "1970-01-01T00:00Z[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[u-ca=hebrew]",
+ "1970-01-01T00:00+01:00[Etc/Ignored][u-ca=hebrew]",
+];
+for (const str of valids) {
+ const result = instance.getPreviousTransition(str);
+ assert.sameValue(result, null);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/leap-second.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/leap-second.js
new file mode 100644
index 0000000000..b2db8c3b61
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/leap-second.js
@@ -0,0 +1,21 @@
+// |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.timezone.prototype.getprevioustransition
+description: Leap second is a valid ISO string for Instant
+features: [Temporal]
+---*/
+
+const instance = new Temporal.TimeZone("UTC");
+
+const arg = "2016-12-31T23:59:60Z";
+const result = instance.getPreviousTransition(arg);
+assert.sameValue(
+ result,
+ null,
+ "leap second is a valid ISO string for Instant"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js
new file mode 100644
index 0000000000..ce577d9e1f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getprevioustransition
+description: Temporal.TimeZone.prototype.getPreviousTransition.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.TimeZone.prototype.getPreviousTransition, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/name.js
new file mode 100644
index 0000000000..863f68d954
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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.timezone.prototype.getprevioustransition
+description: Temporal.TimeZone.prototype.getPreviousTransition.name is "getPreviousTransition".
+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.TimeZone.prototype.getPreviousTransition, "name", {
+ value: "getPreviousTransition",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/not-a-constructor.js
new file mode 100644
index 0000000000..ff62b8aeeb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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.timezone.prototype.getprevioustransition
+description: >
+ Temporal.TimeZone.prototype.getPreviousTransition 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.TimeZone.prototype.getPreviousTransition();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.getPreviousTransition), false,
+ "isConstructor(Temporal.TimeZone.prototype.getPreviousTransition)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/prop-desc.js
new file mode 100644
index 0000000000..06f2b98876
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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.timezone.prototype.getprevioustransition
+description: The "getPreviousTransition" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.getPreviousTransition,
+ "function",
+ "`typeof TimeZone.prototype.getPreviousTransition` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "getPreviousTransition", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/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/TimeZone/prototype/getPreviousTransition/year-zero.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.js
new file mode 100644
index 0000000000..1d0208c42f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/getPreviousTransition/year-zero.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.timezone.prototype.getprevioustransition
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-03-30T00:45Z",
+ "-000000-03-30T01:45+01:00",
+ "-000000-03-30T01:45:00+00:00[UTC]",
+];
+const instance = new Temporal.TimeZone("UTC");
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.getPreviousTransition(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/branding.js
new file mode 100644
index 0000000000..0673aa9475
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/branding.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-get-temporal.timezone.prototype.id
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const descriptor = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "id");
+const id = descriptor.get;
+
+assert.sameValue(typeof id, "function");
+
+assert.throws(TypeError, () => id.call(undefined), "undefined");
+assert.throws(TypeError, () => id.call(null), "null");
+assert.throws(TypeError, () => id.call(true), "true");
+assert.throws(TypeError, () => id.call(""), "empty string");
+assert.throws(TypeError, () => id.call(Symbol()), "symbol");
+assert.throws(TypeError, () => id.call(1), "1");
+assert.throws(TypeError, () => id.call({}), "plain object");
+assert.throws(TypeError, () => id.call(Temporal.TimeZone), "Temporal.TimeZone");
+assert.throws(TypeError, () => id.call(Temporal.TimeZone.prototype), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/custom-timezone.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/custom-timezone.js
new file mode 100644
index 0000000000..31918f4866
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/custom-timezone.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-temporal.timezone.prototype.id
+description: Getter does not call toString(), returns the ID from internal slot
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const actual = [];
+const expected = [];
+
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.observeProperty(actual, timeZone, Symbol.toPrimitive, undefined);
+TemporalHelpers.observeProperty(actual, timeZone, "toString", function () {
+ actual.push("call timeZone.toString");
+ return "time zone";
+});
+
+const result = timeZone.id;
+assert.compareArray(actual, expected);
+assert.sameValue(result, "UTC");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/prop-desc.js
new file mode 100644
index 0000000000..f1e4358ba0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/prop-desc.js
@@ -0,0 +1,17 @@
+// |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-get-temporal.timezone.prototype.id
+description: The "id" property of Temporal.TimeZone.prototype
+features: [Temporal]
+---*/
+
+const descriptor = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "id");
+assert.sameValue(typeof descriptor.get, "function");
+assert.sameValue(descriptor.set, undefined);
+assert.sameValue(descriptor.enumerable, false);
+assert.sameValue(descriptor.configurable, true);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/id/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.js
new file mode 100644
index 0000000000..040655cc05
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/prop-desc.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-timezone-prototype
+description: The "prototype" property of Temporal.TimeZone
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(typeof Temporal.TimeZone.prototype, "object");
+assert.notSameValue(Temporal.TimeZone.prototype, null);
+
+verifyProperty(Temporal.TimeZone, "prototype", {
+ writable: false,
+ enumerable: false,
+ configurable: false,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.js
new file mode 100644
index 0000000000..c2c2d70b43
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/branding.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.timezone.prototype.tojson
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toJSON = Temporal.TimeZone.prototype.toJSON;
+
+assert.sameValue(typeof toJSON, "function");
+
+assert.throws(TypeError, () => toJSON.call(undefined), "undefined");
+assert.throws(TypeError, () => toJSON.call(null), "null");
+assert.throws(TypeError, () => toJSON.call(true), "true");
+assert.throws(TypeError, () => toJSON.call(""), "empty string");
+assert.throws(TypeError, () => toJSON.call(Symbol()), "symbol");
+assert.throws(TypeError, () => toJSON.call(1), "1");
+assert.throws(TypeError, () => toJSON.call({}), "plain object");
+assert.throws(TypeError, () => toJSON.call(Temporal.TimeZone), "Temporal.TimeZone");
+assert.throws(TypeError, () => toJSON.call(Temporal.TimeZone.prototype), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/builtin.js
new file mode 100644
index 0000000000..6be9473aca
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/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.timezone.prototype.tojson
+description: >
+ Tests that Temporal.TimeZone.prototype.toJSON
+ 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.TimeZone.prototype.toJSON),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.toJSON),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.toJSON),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.toJSON.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js
new file mode 100644
index 0000000000..c9643b2cb4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.tojson
+description: Temporal.TimeZone.prototype.toJSON.length is 0
+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.TimeZone.prototype.toJSON, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/name.js
new file mode 100644
index 0000000000..120b740fcb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/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.timezone.prototype.tojson
+description: Temporal.TimeZone.prototype.toJSON.name is "toJSON".
+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.TimeZone.prototype.toJSON, "name", {
+ value: "toJSON",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/not-a-constructor.js
new file mode 100644
index 0000000000..1e2dd72b4b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/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.timezone.prototype.tojson
+description: >
+ Temporal.TimeZone.prototype.toJSON 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.TimeZone.prototype.toJSON();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.toJSON), false,
+ "isConstructor(Temporal.TimeZone.prototype.toJSON)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/prop-desc.js
new file mode 100644
index 0000000000..4d6365274f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/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.timezone.prototype.tojson
+description: The "toJSON" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.toJSON,
+ "function",
+ "`typeof TimeZone.prototype.toJSON` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "toJSON", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/returns-identifier-slot.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/returns-identifier-slot.js
new file mode 100644
index 0000000000..9681aab599
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/returns-identifier-slot.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.tojson
+description: toJSON() returns the internal slot value
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const actual = [];
+
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.observeProperty(actual, timeZone, Symbol.toPrimitive, undefined);
+TemporalHelpers.observeProperty(actual, timeZone, "id", "Etc/Bogus");
+TemporalHelpers.observeProperty(actual, timeZone, "toString", function () {
+ actual.push("call timeZone.toString");
+ return "Etc/TAI";
+});
+
+const result = timeZone.toJSON();
+assert.sameValue(result, "UTC", "toJSON gets the internal slot value");
+assert.compareArray(actual, [], "should not invoke any observable operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toJSON/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/TimeZone/prototype/toString/branding.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/branding.js
new file mode 100644
index 0000000000..ec12ff4fbd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/branding.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.timezone.prototype.tostring
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toString = Temporal.TimeZone.prototype.toString;
+
+assert.sameValue(typeof toString, "function");
+
+assert.throws(TypeError, () => toString.call(undefined), "undefined");
+assert.throws(TypeError, () => toString.call(null), "null");
+assert.throws(TypeError, () => toString.call(true), "true");
+assert.throws(TypeError, () => toString.call(""), "empty string");
+assert.throws(TypeError, () => toString.call(Symbol()), "symbol");
+assert.throws(TypeError, () => toString.call(1), "1");
+assert.throws(TypeError, () => toString.call({}), "plain object");
+assert.throws(TypeError, () => toString.call(Temporal.TimeZone), "Temporal.TimeZone");
+assert.throws(TypeError, () => toString.call(Temporal.TimeZone.prototype), "Temporal.TimeZone.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/builtin.js
new file mode 100644
index 0000000000..d1626775aa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/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.timezone.prototype.tostring
+description: >
+ Tests that Temporal.TimeZone.prototype.toString
+ 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.TimeZone.prototype.toString),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.toString),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.toString),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.TimeZone.prototype.toString.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js
new file mode 100644
index 0000000000..793d2c25f1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2020 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.tostring
+description: Temporal.TimeZone.prototype.toString.length is 0
+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.TimeZone.prototype.toString, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/name.js
new file mode 100644
index 0000000000..1197a8faa9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/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.timezone.prototype.tostring
+description: Temporal.TimeZone.prototype.toString.name is "toString".
+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.TimeZone.prototype.toString, "name", {
+ value: "toString",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/not-a-constructor.js
new file mode 100644
index 0000000000..ce6e8d490a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/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.timezone.prototype.tostring
+description: >
+ Temporal.TimeZone.prototype.toString 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.TimeZone.prototype.toString();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.TimeZone.prototype.toString), false,
+ "isConstructor(Temporal.TimeZone.prototype.toString)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/prop-desc.js
new file mode 100644
index 0000000000..f4b0067d12
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/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.timezone.prototype.tostring
+description: The "toString" property of Temporal.TimeZone.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.TimeZone.prototype.toString,
+ "function",
+ "`typeof TimeZone.prototype.toString` is `function`"
+);
+
+verifyProperty(Temporal.TimeZone.prototype, "toString", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toString/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/TimeZone/prototype/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/prop-desc.js
new file mode 100644
index 0000000000..fae1256a56
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/prop-desc.js
@@ -0,0 +1,19 @@
+// |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.timezone.prototype-@@tostringtag
+description: The @@toStringTag property of Temporal.TimeZone
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.TimeZone.prototype, Symbol.toStringTag, {
+ value: "Temporal.TimeZone",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/TimeZone/prototype/toStringTag/shell.js