summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/built-ins/Temporal/PlainMonthDay
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/PlainMonthDay
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/PlainMonthDay')
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-case-insensitive.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-number.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-string.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js41
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-wrong-type.js40
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js15
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-builtin-calendar-no-array-iteration.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-number.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-plainmonthday.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-case-insensitive.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-leap-second.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-number.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-string.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-wrong-type.js43
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-year-zero.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-calendar-annotation.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-date-with-utc-offset.js63
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-calendar.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-separators.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-zone-annotation.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-unknown-annotation.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-wrong-type.js41
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-datefromfields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-validates-fields.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/constructor-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/duplicate-calendar-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js42
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/leap-second.js44
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-primitive.js39
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-string-invalid.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-object.js22
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js83
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js43
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js37
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js41
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/proto-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js44
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js44
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/prop-desc.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/constructor.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js14
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/custom.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/validate-calendar-value.js41
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-builtin-calendar-no-array-iteration.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-number.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-case-insensitive.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-leap-second.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-number.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-string.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-wrong-type.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-year-zero.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-calendar-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-critical-unknown-annotation.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-date-with-utc-offset.js64
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-invalid.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-calendar.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-time-zone.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-separators.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-zone-annotation.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-unknown-annotation.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js43
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-datefromfields-called-with-null-prototype-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js55
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/constructor-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/duplicate-calendar-fields.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/leap-second.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/proto-in-calendar-fields.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/custom.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prototype.js15
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js15
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js14
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/custom.js30
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/validate-calendar-value.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js54
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js58
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-array-iteration.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-observable-calls.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js37
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fromfields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-mergefields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/constructor-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/default-overflow-behaviour.js17
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/duplicate-calendar-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js33
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/proto-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin-calendar-no-observable-calls.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendar-tostring.js56
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-critical.js50
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js48
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js56
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js49
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-object.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js51
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/order-of-operations.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js58
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/prop-desc.js19
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/branding.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js44
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/branding.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/browser.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-array-iteration.js23
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-observable-calls.js46
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js36
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js32
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js21
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/constructor-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js34
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/duplicate-calendar-fields.js18
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js25
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js28
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-object.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js26
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js76
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js31
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js29
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js27
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/proto-in-calendar-fields.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js24
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-out-of-range.js16
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js20
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js0
-rw-r--r--js/src/tests/test262/built-ins/Temporal/PlainMonthDay/subclass.js21
273 files changed, 7073 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.js
new file mode 100644
index 0000000000..a0edb834b5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/basic.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.plainmonthday
+description: Basic tests for the PlainMonthDay constructor.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const leapDay = new Temporal.PlainMonthDay(2, 29);
+TemporalHelpers.assertPlainMonthDay(leapDay, "M02", 29, "leap day is supported");
+assert.sameValue(leapDay.calendarId, "iso8601", "leap day calendar");
+
+const beforeEpoch = new Temporal.PlainMonthDay(12, 2, "iso8601", 1920);
+TemporalHelpers.assertPlainMonthDay(beforeEpoch, "M12", 2, "reference year before epoch", 1920);
+assert.sameValue(beforeEpoch.calendarId, "iso8601", "reference year before epoch calendar");
+
+const afterEpoch = new Temporal.PlainMonthDay(1, 7, "iso8601", 1980);
+TemporalHelpers.assertPlainMonthDay(afterEpoch, "M01", 7, "reference year after epoch", 1980);
+assert.sameValue(afterEpoch.calendarId, "iso8601", "reference year after epoch calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js
new file mode 100644
index 0000000000..0f9124ee4a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/builtin.js
@@ -0,0 +1,30 @@
+// |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.plainmonthday
+description: Tests that Temporal.PlainMonthDay meets the requirements for built-in objects
+info: |
+ 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.PlainMonthDay),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay),
+ Function.prototype, "prototype");
+
+assert.sameValue(typeof Temporal.PlainMonthDay.prototype,
+ "object", "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.js
new file mode 100644
index 0000000000..727a72bfe5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-always.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.plainmonthday
+description: If calendar name is to be emitted, include additional reference info
+features: [Temporal]
+---*/
+
+const pmd = new Temporal.PlainMonthDay(10, 31, "iso8601", 2019);
+
+assert.sameValue(
+ pmd.toString({ calendarName: 'always' }),
+ "2019-10-31[u-ca=iso8601]",
+ "emit year-month-day if calendarName = 'always' (four-argument constructor)"
+);
+
+const anotherPMD = Temporal.PlainMonthDay.from("2019-10-31"); // 2019 will get dropped
+
+assert.sameValue(
+ anotherPMD.toString({ calendarName: 'always' }),
+ "1972-10-31[u-ca=iso8601]",
+ "emit fallback year if calendarName = 'always' (static from)"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-case-insensitive.js
new file mode 100644
index 0000000000..3bf53f6ba0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-case-insensitive.js
@@ -0,0 +1,16 @@
+// |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.plainmonthday
+description: Calendar names are case-insensitive
+features: [Temporal]
+---*/
+
+const arg = "iSo8601";
+
+const result = new Temporal.PlainMonthDay(12, 15, arg, 1972);
+assert.sameValue(result.calendarId, "iso8601", "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.js
new file mode 100644
index 0000000000..5d26677c45
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-invalid.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.
+
+/*---
+description: Temporal.PlainMonthDay throws a RangeError if the calendar argument is invalid
+esid: sec-temporal.plainmonthday
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"];
+const actual = [];
+const args = [
+ TemporalHelpers.toPrimitiveObserver(actual, 2, "month"),
+ TemporalHelpers.toPrimitiveObserver(actual, 1, "day"),
+ "local",
+ TemporalHelpers.toPrimitiveObserver(actual, 1, "year")
+];
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args));
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-number.js
new file mode 100644
index 0000000000..539d444e0e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-number.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.plainmonthday
+description: A number is not allowed to be a calendar
+features: [Temporal]
+---*/
+
+const numbers = [
+ 1,
+ -19761118,
+ 19761118,
+ 1234567890,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => new Temporal.PlainMonthDay(12, 15, arg, 1972),
+ "A number is not a valid ISO string for Calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-string.js
new file mode 100644
index 0000000000..06e5c4938c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-string.js
@@ -0,0 +1,16 @@
+// |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.plainmonthday.constructor
+description: A calendar ID is valid input for Calendar
+features: [Temporal]
+---*/
+
+const arg = "iso8601";
+
+const result = new Temporal.PlainMonthDay(12, 15, arg, 1972);
+assert.sameValue(result.getISOFields().calendar, "iso8601", `Calendar created from string "${arg}"`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js
new file mode 100644
index 0000000000..910285cd61
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-temporal-object.js
@@ -0,0 +1,41 @@
+// |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.plainmonthday
+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 result = new Temporal.PlainMonthDay(12, 15, arg, 1972);
+ 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/PlainMonthDay/calendar-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.js
new file mode 100644
index 0000000000..9db2f4c1a8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-undefined.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.plainmonthday
+description: Calendar argument defaults to the built-in ISO 8601 calendar
+features: [Temporal]
+---*/
+
+const args = [5, 2];
+
+Object.defineProperty(Temporal.Calendar, "from", {
+ get() {
+ throw new Test262Error("Should not get Calendar.from");
+ },
+});
+
+const dateExplicit = new Temporal.PlainMonthDay(...args, undefined);
+assert.sameValue(dateExplicit.calendarId, "iso8601");
+
+const dateImplicit = new Temporal.PlainMonthDay(...args);
+assert.sameValue(dateImplicit.calendarId, "iso8601");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-wrong-type.js
new file mode 100644
index 0000000000..83fc7ee16b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/calendar-wrong-type.js
@@ -0,0 +1,40 @@
+// |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.plainmonthday
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or object for Calendar
+features: [BigInt, Symbol, Temporal]
+---*/
+
+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,
+ () => new Temporal.PlainMonthDay(12, 15, arg, 1972),
+ `${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, () => new Temporal.PlainMonthDay(12, 15, arg, 1972), `${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/PlainMonthDay/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js
new file mode 100644
index 0000000000..d5bdac8122
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/constructor.js
@@ -0,0 +1,15 @@
+// |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.plainmonthday
+description: Temporal.PlainMonthDay constructor cannot be called as a function
+info: |
+ 1. If NewTarget is undefined, throw a TypeError exception.
+features: [Temporal]
+---*/
+
+assert.throws(TypeError, () => Temporal.PlainMonthDay(1, 2));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..b94b0658d4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-builtin-calendar-no-array-iteration.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.from
+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 arg = { monthCode: "M11", day: 23, calendar: "iso8601" };
+Temporal.PlainMonthDay.from(arg);
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-number.js
new file mode 100644
index 0000000000..1296a24842
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-number.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.plainmonthday.from
+description: A number is invalid in place of an ISO string for Temporal.PlainMonthDay
+features: [Temporal]
+---*/
+
+const numbers = [
+ 1,
+ 1118,
+ -1118,
+ 12345,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ `A number (${arg}) is not a valid ISO string for PlainMonthDay`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-plainmonthday.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-plainmonthday.js
new file mode 100644
index 0000000000..720ab148ac
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-plainmonthday.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.plainmonthday.from
+description: A PlainMonthDay object is copied, not returned directly
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const orig = new Temporal.PlainMonthDay(5, 2, undefined, 2000);
+const result = Temporal.PlainMonthDay.from(orig);
+
+TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ "PlainMonthDay is copied",
+ /* isoYear = */ 2000
+);
+
+assert.sameValue(result.getISOFields().calendar, orig.getISOFields().calendar, "Calendar is copied");
+
+assert.notSameValue(
+ result,
+ orig,
+ "When a PlainMonthDay is given, the returned value is not the original PlainMonthDay"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-case-insensitive.js
new file mode 100644
index 0000000000..a0aeefedf6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-case-insensitive.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.plainmonthday.from
+description: The calendar name is case-insensitive
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = "IsO8601";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = Temporal.PlainMonthDay.from(arg);
+TemporalHelpers.assertPlainMonthDay(result, "M11", 18, "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-leap-second.js
new file mode 100644
index 0000000000..63643396dc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-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.plainmonthday.from
+description: Leap second is a valid ISO string for a calendar in a property bag
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = "2016-12-31T23:59:60";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = Temporal.PlainMonthDay.from(arg);
+TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M11", 18,
+ "leap second is a valid ISO string for calendar"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-number.js
new file mode 100644
index 0000000000..864b362345
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-number.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.plainmonthday.from
+description: A number as calendar in a property bag is not accepted
+features: [Temporal]
+---*/
+
+const numbers = [
+ 1,
+ 19970327,
+ -19970327,
+ 1234567890,
+];
+
+for (const calendar of numbers) {
+ const arg = { monthCode: "M11", day: 18, calendar };
+ assert.throws(
+ TypeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ "Numbers cannot be used as a calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-string.js
new file mode 100644
index 0000000000..2e791bc72b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+description: A calendar ID is valid input for Calendar
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = "iso8601";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = Temporal.PlainMonthDay.from(arg);
+TemporalHelpers.assertPlainMonthDay(result, "M11", 18, `Calendar created from string "${calendar}"`);
+assert.sameValue(result.getISOFields().calendar, "iso8601", "calendar slot stores a string");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-wrong-type.js
new file mode 100644
index 0000000000..870b265522
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-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.plainmonthday.from
+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 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,
+ () => Temporal.PlainMonthDay.from(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, () => Temporal.PlainMonthDay.from(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/PlainMonthDay/from/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-propertybag-calendar-year-zero.js
new file mode 100644
index 0000000000..19fb53023f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+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]",
+];
+
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..bccd2d2e2f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-calendar-annotation.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.plainmonthday.from
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[u-ca=iso8601]", "without time zone"],
+ ["1976-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"],
+ ["1976-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"],
+ ["1976-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"],
+ ["1976-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"],
+];
+
+tests.forEach(([arg, description]) => {
+ const result = Temporal.PlainMonthDay.from(arg);
+
+ TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..bc64a74f38
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+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]",
+];
+
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..6babb740bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-date-with-utc-offset.js
@@ -0,0 +1,63 @@
+// |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.plainmonthday.from
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const validStrings = [
+ "05-02[Asia/Katmandu]",
+ "05-02[!Asia/Katmandu]",
+ "05-02[u-ca=iso8601]",
+ "05-02[Asia/Tokyo][u-ca=iso8601]",
+ "--05-02[Asia/Katmandu]",
+ "--05-02[!Asia/Katmandu]",
+ "--05-02[u-ca=iso8601]",
+ "--05-02[Asia/Tokyo][u-ca=iso8601]",
+ "2000-05-02T00+00:00",
+ "2000-05-02T00+00:00[UTC]",
+ "2000-05-02T00-02:30[America/St_Johns]",
+];
+
+for (const arg of validStrings) {
+ const result = Temporal.PlainMonthDay.from(arg);
+
+ TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ `"${arg}" is a valid UTC offset with time for PlainMonthDay`
+ );
+}
+
+const invalidStrings = [
+ "09-15Z",
+ "09-15Z[UTC]",
+ "09-15+01:00",
+ "09-15+01:00[Europe/Vienna]",
+ "--09-15Z",
+ "--09-15Z[UTC]",
+ "--09-15+01:00",
+ "--09-15+01:00[Europe/Vienna]",
+ "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]",
+ "09-15[u-ca=chinese]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ `"${arg}" UTC offset without time is not valid for PlainMonthDay`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..0ea75ba1d0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+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]",
+];
+
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..7801034dc8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+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]",
+];
+
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-separators.js
new file mode 100644
index 0000000000..14812c97f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-separators.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.plainmonthday.from
+description: Time separator in string argument can vary
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23", "uppercase T"],
+ ["1976-05-02t15:23", "lowercase T"],
+ ["1976-05-02 15:23", "space between date and time"],
+];
+
+tests.forEach(([arg, description]) => {
+ const result = Temporal.PlainMonthDay.from(arg);
+
+ TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..f4b348d0bb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-time-zone-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.plainmonthday.from
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[Asia/Kolkata]", "named, with no offset"],
+ ["1976-05-02T15:23[!Europe/Vienna]", "named, with ! and no offset"],
+ ["1976-05-02T15:23[+00:00]", "numeric, with no offset"],
+ ["1976-05-02T15:23[!-02:30]", "numeric, with ! and no offset"],
+ ["1976-05-02T15:23+00:00[UTC]", "named, with offset"],
+ ["1976-05-02T15:23+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1976-05-02T15:23+00:00[+01:00]", "numeric, with offset"],
+ ["1976-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"],
+];
+
+tests.forEach(([arg, description]) => {
+ const result = Temporal.PlainMonthDay.from(arg);
+
+ TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..ec7d10884f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-unknown-annotation.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.plainmonthday.from
+description: Various forms of unknown annotation
+features: [Temporal]
+includes: [temporalHelpers.js]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[foo=bar]", "alone"],
+ ["1976-05-02T15:23[UTC][foo=bar]", "with time zone"],
+ ["1976-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1976-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1976-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+tests.forEach(([arg, description]) => {
+ const result = Temporal.PlainMonthDay.from(arg);
+
+ TemporalHelpers.assertPlainMonthDay(
+ result,
+ "M05", 2,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.js
new file mode 100644
index 0000000000..c2591c4eec
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-string-with-utc-designator.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.plainmonthday.from
+description: RangeError thrown if a string with UTC designator is used as a PlainMonthDay
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "2019-10-01T09:00:00Z",
+ "2019-10-01T09:00:00Z[UTC]",
+];
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ "String with UTC designator should not be valid as a PlainMonthDay"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-wrong-type.js
new file mode 100644
index 0000000000..7ee63cf148
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/argument-wrong-type.js
@@ -0,0 +1,41 @@
+// |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.plainmonthday.from
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or property bag for PlainMonthDay
+features: [BigInt, Symbol, Temporal]
+---*/
+
+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,
+ () => Temporal.PlainMonthDay.from(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object"],
+ [Temporal.PlainMonthDay, "Temporal.PlainMonthDay, object"],
+ [Temporal.PlainMonthDay.prototype, "Temporal.PlainMonthDay.prototype, object"],
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => Temporal.PlainMonthDay.from(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/PlainMonthDay/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js
new file mode 100644
index 0000000000..7863e22457
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/builtin.js
@@ -0,0 +1,33 @@
+// |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.plainmonthday.from
+description: Tests that Temporal.PlainMonthDay.from meets the requirements for built-in objects
+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.PlainMonthDay.from),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.from),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.from),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.from.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-datefromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..3fba4ca9b7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-datefromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.from
+description: >
+ Calendar.monthDayFromFields method is called with a null-prototype fields object
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
+const arg = { monthCode: "M05", day: 2, calendar };
+Temporal.PlainMonthDay.from(arg);
+assert.sameValue(calendar.monthDayFromFieldsCallCount, 1, "monthDayFromFields should be called on the property bag's calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js
new file mode 100644
index 0000000000..507085975d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-fields-iterable.js
@@ -0,0 +1,33 @@
+// |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.plainmonthday.from
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.plainmonthday.from step 3:
+ 3. Return ? ToTemporalMonthDay(_item_, _options_).
+ sec-temporal-totemporalmonthday step 2.f:
+ f. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
+ sec-temporal-calendarfields step 4:
+ 4. Let _result_ be ? IterableToList(_fieldsArray_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "day",
+ "month",
+ "monthCode",
+ "year",
+];
+
+const calendar = TemporalHelpers.calendarFieldsIterable();
+Temporal.PlainMonthDay.from({ monthCode: "M05", 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/PlainMonthDay/from/calendar-monthdayfromfields-validates-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-validates-fields.js
new file mode 100644
index 0000000000..6f966f881f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-validates-fields.js
@@ -0,0 +1,34 @@
+// |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.plainmonthday.from
+description: >
+ Calendar.monthDayFromFields method validates which fields must be present
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = new class extends Temporal.Calendar {
+ fields(fields) {
+ return fields.slice().concat("fnord");
+ }
+ monthDayFromFields(fields) {
+ // accept everything except fnord
+ assert.sameValue(fields.fnord, undefined);
+ return new Temporal.PlainMonthDay(1, 1, this, 1972);
+ }
+}("iso8601");
+
+// This would throw on any non-ISO builtin calendar
+const result = Temporal.PlainMonthDay.from({ month: 8, day: 16, calendar });
+TemporalHelpers.assertPlainMonthDay(result, "M01", 1, "monthDayFromFields determines what fields are necessary")
+
+assert.throws(
+ Test262Error,
+ () => Temporal.PlainMonthDay.from({ monthCode: "M09", day: 19, fnord: "fnord", calendar }),
+ "monthDayFromFields determines what fields are disallowed"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/calendar-temporal-object.js
new file mode 100644
index 0000000000..7820bbb8bd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
+info: |
+ sec-temporal.plainmonthday.from step 3:
+ 3. Return ? ToTemporalMonthDay(_item_, _options_).
+ sec-temporal-totemporalmonthday step 3.e:
+ e. 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, calendar) => {
+ const result = Temporal.PlainMonthDay.from({ monthCode: "M05", day: 2, calendar: temporalObject });
+ assert.sameValue(result.getCalendar(), calendar, "Temporal object coerced to calendar");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..5f47f9111f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/constructor-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.from
+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};
+
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..d12829d43c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.prototype.from
+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'], ['month'], ['monthCode'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar };
+
+ assert.throws(RangeError, () => Temporal.PlainMonthDay.from(arg));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.js
new file mode 100644
index 0000000000..fd1591dd70
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-leap-day.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.plainmonthday.from
+description: Basic tests for PlainMonthDay.from(string).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+// Leap years
+["reject", "constrain"].forEach((overflow) => {
+ const string = Temporal.PlainMonthDay.from("02-29", { overflow });
+ TemporalHelpers.assertPlainMonthDay(string, "M02", 29, `from ${overflow} string`);
+
+ const monthCode = Temporal.PlainMonthDay.from({ monthCode: "M02", day: 29 }, { overflow });
+ TemporalHelpers.assertPlainMonthDay(monthCode, "M02", 29, `from ${overflow} with monthCode`);
+
+ const implicit = Temporal.PlainMonthDay.from({ month: 2, day: 29 }, { overflow });
+ TemporalHelpers.assertPlainMonthDay(implicit, "M02", 29, `from ${overflow} without year`);
+
+ const explicit = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 1996 }, { overflow });
+ TemporalHelpers.assertPlainMonthDay(explicit, "M02", 29, `from ${overflow} with leap year`);
+});
+
+// Non-leap years
+assert.throws(RangeError,
+ () => Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001 }, { overflow: "reject" }),
+ "from reject with non-leap year");
+
+const nonLeap = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001 }, { overflow: "constrain" });
+TemporalHelpers.assertPlainMonthDay(nonLeap, "M02", 28, "from constrain with non-leap year");
+
+assert.throws(RangeError,
+ () => Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001, calendar: "iso8601" }, { overflow: "reject" }),
+ "from reject with non-leap year and explicit calendar");
+
+const nonLeapCalendar = Temporal.PlainMonthDay.from({ month: 2, day: 29, year: 2001, calendar: "iso8601" }, { overflow: "constrain" });
+TemporalHelpers.assertPlainMonthDay(nonLeapCalendar, "M02", 28, "from constrain with non-leap year and explicit calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.js
new file mode 100644
index 0000000000..9b706bf645
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-missing-properties.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-temporal.plainmonthday.from
+description: Basic tests for PlainMonthDay.from(object) with missing properties.
+features: [Temporal]
+---*/
+
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from({}), "No properties");
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ day: 15 }), "Only day");
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: 'M12' }), "Only monthCode");
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: undefined, day: 15 }), "monthCode undefined");
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ months: 12, day: 31 }), "months plural");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js
new file mode 100644
index 0000000000..c41950ba28
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-object.js
@@ -0,0 +1,33 @@
+// |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.plainmonthday.from
+description: Basic tests for PlainMonthDay.from(object).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const tests = [
+ [{ monthCode: "M10", day: 1 }, "option bag with monthCode"],
+ [{ monthCode: "M10", day: 1, year: 2015 }, "option bag with year, monthCode"],
+ [{ month: 10, day: 1 }, "option bag with year, month"],
+ [{ month: 10, day: 1, year: 2015 }, "option bag with year, month"],
+ [{ month: 10, day: 1, days: 31 }, "option bag with plural 'days'"],
+ [new Temporal.PlainMonthDay(10, 1), "PlainMonthDay object"],
+ [Temporal.PlainDate.from("2019-10-01"), "PlainDate object"],
+ [{ monthCode: "M10", day: 1, calendar: "iso8601" }, "option bag with monthCode and explicit ISO calendar"],
+ [{ month: 10, day: 1, calendar: "iso8601" }, "option bag with month and explicit ISO calendar"],
+ [{ monthCode: "M10", day: 1, calendar: Temporal.Calendar.from("iso8601") }, "option bag with monthCode and object ISO calendar"],
+ [{ month: 10, day: 1, calendar: Temporal.Calendar.from("iso8601") }, "option bag with month and object ISO calendar"],
+];
+
+for (const [argument, description = argument] of tests) {
+ const plainMonthDay = Temporal.PlainMonthDay.from(argument);
+ assert.notSameValue(plainMonthDay, argument, `from ${description} converts`);
+ TemporalHelpers.assertPlainMonthDay(plainMonthDay, "M10", 1, `from ${description}`);
+ assert.sameValue(plainMonthDay.calendarId, "iso8601", `from ${description} calendar`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js
new file mode 100644
index 0000000000..7950b7979d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-plainmonthday.js
@@ -0,0 +1,30 @@
+// |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.plainmonthday.from
+description: Basic tests for PlainMonthDay.from(PlainMonthDay).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get overflow",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const options = {
+ get overflow() {
+ actual.push("get overflow");
+ return TemporalHelpers.toPrimitiveObserver(actual, "reject", "overflow");
+ }
+};
+
+const fields = new Temporal.PlainMonthDay(11, 16, undefined, 1960);
+const result = Temporal.PlainMonthDay.from(fields, options);
+TemporalHelpers.assertPlainMonthDay(result, "M11", 16, "should copy reference year", 1960);
+assert.compareArray(actual, expected, "Should get overflow");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.js
new file mode 100644
index 0000000000..4b2abea439
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/fields-string.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.plainmonthday.from
+description: Basic tests for PlainMonthDay.from(string).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+for (const argument of TemporalHelpers.ISO.plainMonthDayStringsValid()) {
+ const plainMonthDay = Temporal.PlainMonthDay.from(argument);
+ assert.notSameValue(plainMonthDay, argument, `from ${argument} converts`);
+ TemporalHelpers.assertPlainMonthDay(plainMonthDay, "M10", 1, `from ${argument}`);
+ assert.sameValue(plainMonthDay.calendarId, "iso8601", `from ${argument} calendar`);
+}
+
+for (const arg of TemporalHelpers.ISO.plainMonthDayStringsInvalid()) {
+ assert.throws(RangeError, () => Temporal.PlainMonthDay.from(arg), `"${arg}" not a valid PlainMonthDay string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..25835f1fc5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/infinity-throws-rangeerror.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Throws if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.plainmonthday.from
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const base = { year: 2000, month: 5, day: 2 };
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["year", "month", "day"].forEach((prop) => {
+ ["constrain", "reject"].forEach((overflow) => {
+ assert.throws(RangeError, () => Temporal.PlainMonthDay.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
+ assert.throws(RangeError, () => Temporal.PlainMonthDay.from({ ...base, [prop]: obj }, { overflow }));
+ assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value");
+ });
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/leap-second.js
new file mode 100644
index 0000000000..eb6ec3ad07
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/leap-second.js
@@ -0,0 +1,44 @@
+// |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.plainmonthday.from
+description: Leap second is a valid ISO string for PlainMonthDay
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+let arg = "2016-12-31T23:59:60";
+
+const result1 = Temporal.PlainMonthDay.from(arg);
+TemporalHelpers.assertPlainMonthDay(
+ result1,
+ "M12", 31,
+ "leap second is a valid ISO string for PlainMonthDay"
+);
+
+const result2 = Temporal.PlainMonthDay.from(arg, { overflow: "reject" });
+TemporalHelpers.assertPlainMonthDay(
+ result2,
+ "M12", 31,
+ "leap second is a valid ISO string for PlainMonthDay"
+);
+
+arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
+
+const result3 = Temporal.PlainMonthDay.from(arg);
+TemporalHelpers.assertPlainMonthDay(
+ result3,
+ "M12", 31,
+ "second: 60 is ignored in property bag for PlainMonthDay"
+);
+
+const result4 = Temporal.PlainMonthDay.from(arg, { overflow: "reject" });
+TemporalHelpers.assertPlainMonthDay(
+ result4,
+ "M12", 31,
+ "second: 60 is ignored in property bag for PlainMonthDay even with overflow: reject"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/length.js
new file mode 100644
index 0000000000..2d96ee9b53
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+description: Temporal.PlainMonthDay.from.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.PlainMonthDay.from, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.js
new file mode 100644
index 0000000000..b6f2ea00b4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/name.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.plainmonthday.from
+description: Temporal.PlainMonthDay.from.name is "from"
+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.PlainMonthDay.from, "name", {
+ value: "from",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.js
new file mode 100644
index 0000000000..593b6635ea
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/not-a-constructor.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.plainmonthday.from
+description: Temporal.PlainMonthDay.from 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.PlainMonthDay.from();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.from), false,
+ "isConstructor(Temporal.PlainMonthDay.from)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-primitive.js
new file mode 100644
index 0000000000..7544949b8e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-primitive.js
@@ -0,0 +1,39 @@
+// |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.plainmonthday.from
+description: overflow property is extracted with string argument.
+info: |
+ 1. Perform ? ToTemporalOverflow(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+ "get options.overflow.toString",
+ "call options.overflow.toString",
+];
+
+let actual = [];
+const options = TemporalHelpers.propertyBagObserver(actual, { overflow: "constrain" }, "options");
+
+const result = Temporal.PlainMonthDay.from("05-17", options);
+assert.compareArray(actual, expected, "Successful call");
+TemporalHelpers.assertPlainMonthDay(result, "M05", 17);
+
+actual.splice(0); // empty it for the next check
+const failureExpected = [
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+];
+
+assert.throws(TypeError, () => Temporal.PlainMonthDay.from(7, options));
+assert.compareArray(actual, failureExpected, "Failing call");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-string-invalid.js
new file mode 100644
index 0000000000..d3bd9683cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/observable-get-overflow-argument-string-invalid.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.plainmonthday.from
+description: overflow property is extracted with ISO-invalid string argument.
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+];
+
+let actual = [];
+const options = TemporalHelpers.propertyBagObserver(actual, { overflow: "constrain" }, "options");
+
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from("13-34", options));
+assert.compareArray(actual, expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.js
new file mode 100644
index 0000000000..66a571d18c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-invalid.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.plainmonthday.from
+description: TypeError thrown when options argument is a primitive
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const fields = { month: 2, day: 31 };
+
+const values = [null, true, "hello", Symbol("foo"), 1, 1n];
+for (const badOptions of values) {
+ assert.throws(TypeError, () => Temporal.PlainMonthDay.from(fields, badOptions));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-object.js
new file mode 100644
index 0000000000..e72fb46bdb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-object.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.plainmonthday.prototype.from
+description: Empty object may be used as options
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.assertPlainMonthDay(
+ Temporal.PlainMonthDay.from({ monthCode: "M12", day: 15 }, {}), "M12", 15,
+ "options may be an empty plain object"
+);
+
+TemporalHelpers.assertPlainMonthDay(
+ Temporal.PlainMonthDay.from({ monthCode: "M12", day: 15 }, () => {}), "M12", 15,
+ "options may be an empty function object"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js
new file mode 100644
index 0000000000..72925d679d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-undefined.js
@@ -0,0 +1,20 @@
+// |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.plainmonthday.from
+includes: [temporalHelpers.js]
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+---*/
+
+const fields = { month: 2, day: 31 };
+
+const explicit = Temporal.PlainMonthDay.from(fields, undefined);
+TemporalHelpers.assertPlainMonthDay(explicit, "M02", 29, "default overflow is constrain");
+
+const implicit = Temporal.PlainMonthDay.from(fields);
+TemporalHelpers.assertPlainMonthDay(implicit, "M02", 29, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js
new file mode 100644
index 0000000000..420269cff3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.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.plainmonthday.from
+description: TypeError thrown when options argument is a primitive
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const badOptions = [
+ null,
+ true,
+ "some string",
+ Symbol(),
+ 1,
+ 2n,
+];
+
+for (const value of badOptions) {
+ assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: "M12", day: 15 }, value),
+ `TypeError on wrong options type ${typeof value}`);
+};
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js
new file mode 100644
index 0000000000..fc28c00f21
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/order-of-operations.js
@@ -0,0 +1,83 @@
+// |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.plainmonthday.from
+description: Properties on an object passed to from() are accessed in the correct order
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ // CopyDataProperties
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+ "getOwnPropertyDescriptor options.extra",
+ "get options.extra",
+ "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.fields",
+ "get fields.calendar.monthDayFromFields",
+ // CalendarFields
+ "call fields.calendar.fields",
+ // PrepareTemporalFields
+ "get fields.day",
+ "get fields.day.valueOf",
+ "call fields.day.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.year",
+ "get fields.year.valueOf",
+ "call fields.year.valueOf",
+ // CalendarMonthDayFromFields
+ "call fields.calendar.monthDayFromFields",
+ // inside Calendar.p.monthDayFromFields
+ "get options.overflow.toString",
+ "call options.overflow.toString",
+];
+const actual = [];
+
+const fields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 1.7,
+ month: 1.7,
+ monthCode: "M01",
+ day: 1.7,
+ calendar: TemporalHelpers.calendarObserver(actual, "fields.calendar"),
+}, "fields");
+
+const options = TemporalHelpers.propertyBagObserver(actual, {
+ overflow: "constrain",
+ extra: "property",
+}, "options");
+
+Temporal.PlainMonthDay.from(fields, options);
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..ab37726490
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js
@@ -0,0 +1,43 @@
+// |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.plainmonthday.from
+description: RangeError thrown when overflow option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-totemporalmonthday steps 3–4:
+ 3. If Type(_item_) is Object, then
+ ...
+ j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+ 4. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalMonthDay(_item_, _options_).
+features: [Temporal]
+---*/
+
+const validValues = [
+ new Temporal.PlainMonthDay(5, 2),
+ { monthCode: "M05", day: 2 },
+ "05-02",
+];
+
+const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"];
+for (const value of validValues) {
+ for (const overflow of badOverflows) {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(value, { overflow }),
+ `invalid overflow ("${overflow}")`
+ );
+ }
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.js
new file mode 100644
index 0000000000..5b47d26db5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-undefined.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.plainmonthday.from
+description: Fallback value for overflow option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-totemporalmonthday steps 3–4:
+ 3. If Type(_item_) is Object, then
+ ...
+ j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+ 4. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalMonthDay(_item_, _options_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const validValues = [
+ new Temporal.PlainMonthDay(5, 2),
+ "05-02",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.PlainMonthDay.from(value, { overflow: undefined });
+ TemporalHelpers.assertPlainMonthDay(explicit, "M05", 2, "overflow is ignored");
+ const implicit = Temporal.PlainMonthDay.from(value, {});
+ TemporalHelpers.assertPlainMonthDay(implicit, "M05", 2, "overflow is ignored");
+ const lambda = Temporal.PlainMonthDay.from(value, () => {});
+ TemporalHelpers.assertPlainMonthDay(lambda, "M05", 2, "overflow is ignored");
+});
+
+const propertyBag = { year: 2000, month: 13, day: 34 };
+const explicit = Temporal.PlainMonthDay.from(propertyBag, { overflow: undefined });
+TemporalHelpers.assertPlainMonthDay(explicit, "M12", 31, "default overflow is constrain");
+const implicit = Temporal.PlainMonthDay.from(propertyBag, {});
+TemporalHelpers.assertPlainMonthDay(implicit, "M12", 31, "default overflow is constrain");
+const lambda = Temporal.PlainMonthDay.from(propertyBag, () => {});
+TemporalHelpers.assertPlainMonthDay(lambda, "M12", 31, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..3c022d6f6e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow-wrong-type.js
@@ -0,0 +1,37 @@
+// |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.plainmonthday.from
+description: Type conversions for overflow option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-totemporalmonthday steps 3–4:
+ 3. If Type(_item_) is Object, then
+ ...
+ j. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+ 4. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalMonthDay]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalMonthDay(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const validValues = [
+ new Temporal.PlainMonthDay(5, 2),
+ { monthCode: "M05", day: 2 },
+ "05-02",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.PlainMonthDay.from(value, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr),
+));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js
new file mode 100644
index 0000000000..11168dad82
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/overflow.js
@@ -0,0 +1,41 @@
+// |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.plainmonthday.from
+description: Handling for overflow option
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const validValues = [
+ new Temporal.PlainMonthDay(5, 2),
+ "05-02",
+];
+validValues.forEach((value) => {
+ const constrain = Temporal.PlainMonthDay.from(value, { overflow: "constrain" });
+ TemporalHelpers.assertPlainMonthDay(constrain, "M05", 2, "overflow is ignored: constrain");
+
+ const reject = Temporal.PlainMonthDay.from(value, { overflow: "reject" });
+ TemporalHelpers.assertPlainMonthDay(reject, "M05", 2, "overflow is ignored: reject");
+});
+
+const propertyBag1 = { year: 2000, month: 13, day: 34 };
+const result1 = Temporal.PlainMonthDay.from(propertyBag1, { overflow: "constrain" });
+TemporalHelpers.assertPlainMonthDay(result1, "M12", 31, "default overflow is constrain");
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from(propertyBag1, { overflow: "reject" }),
+ "invalid property bag: reject");
+
+const propertyBag2 = { month: 1, day: 32 };
+const result2 = Temporal.PlainMonthDay.from(propertyBag2, { overflow: "constrain" });
+TemporalHelpers.assertPlainMonthDay(result2, "M01", 31, "default overflow is constrain");
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from(propertyBag2, { overflow: "reject" }),
+ "invalid property bag: reject");
+
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from("13-34", { overflow: "constrain" }),
+ "invalid ISO string: constrain");
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from("13-34", { overflow: "reject" }),
+ "invalid ISO string: reject");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/prop-desc.js
new file mode 100644
index 0000000000..015eb6a725
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+description: The "from" property of Temporal.PlainMonthDay
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.from,
+ "function",
+ "`typeof PlainMonthDay.from` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay, "from", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..31281e1772
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/proto-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.from
+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};
+
+assert.throws(RangeError, () => Temporal.PlainMonthDay.from(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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/PlainMonthDay/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.js
new file mode 100644
index 0000000000..1491ef7375
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/subclassing-ignored.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.plainmonthday.from
+description: The receiver is never called when calling from()
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkSubclassingIgnoredStatic(
+ Temporal.PlainMonthDay,
+ "from",
+ ["05-02"],
+ (result) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/year-zero.js
new file mode 100644
index 0000000000..e9befb86e6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/from/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.plainmonthday.from
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-08-24",
+ "-000000-08-24T15:43:27",
+ "-000000-08-24T15:43:27+01:00",
+ "-000000-08-24T15:43:27+00:00[UTC]",
+];
+
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => Temporal.PlainMonthDay.from(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..9a06c133e5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/infinity-throws-rangeerror.js
@@ -0,0 +1,44 @@
+// |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.
+
+/*---
+description: Temporal.PlainMonthDay throws a RangeError if any numerical value is Infinity
+esid: sec-temporal.plainmonthday
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const isoCalendar = Temporal.Calendar.from('iso8601');
+
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(Infinity, 1));
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, Infinity));
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, 1, isoCalendar, Infinity));
+
+const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName);
+const tests = [
+ [
+ "infinite month",
+ [O(Infinity, "month"), O(1, "day"), () => "iso8601", O(1, "year")],
+ ["get month.valueOf", "call month.valueOf"]
+ ],
+ [
+ "infinite day",
+ [O(2, "month"), O(Infinity, "day"), () => "iso8601", O(1, "year")],
+ ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"]
+ ],
+ [
+ "infinite year",
+ [O(2, "month"), O(1, "day"), () => "iso8601", O(Infinity, "year")],
+ ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf", "get year.valueOf", "call year.valueOf"]
+ ],
+];
+
+for (const [description, args, expected] of tests) {
+ const actual = [];
+ const args_ = args.map((o) => o(actual));
+ assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args_), description);
+ assert.compareArray(actual, expected, `${description} order of operations`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js
new file mode 100644
index 0000000000..6e0ad87b85
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/length.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday
+description: Temporal.PlainMonthDay.length is 2
+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.PlainMonthDay, "length", {
+ value: 2,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.js
new file mode 100644
index 0000000000..31432de575
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/missing-arguments.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.plainmonthday
+description: RangeError thrown after processing given args when invoked without all required args
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get month.valueOf",
+ "call month.valueOf",
+];
+const actual = [];
+const args = [
+ TemporalHelpers.toPrimitiveObserver(actual, 1, "month"),
+];
+
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args));
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/name.js
new file mode 100644
index 0000000000..97b592bc6c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday
+description: Temporal.PlainMonthDay.name is "PlainMonthDay"
+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.PlainMonthDay, "name", {
+ value: "PlainMonthDay",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..e58818719d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/negative-infinity-throws-rangeerror.js
@@ -0,0 +1,44 @@
+// |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.
+
+/*---
+description: Temporal.PlainMonthDay throws a RangeError if any numerical value is -Infinity
+esid: sec-temporal.plainmonthday
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const isoCalendar = Temporal.Calendar.from('iso8601');
+
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(-Infinity, 1));
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, -Infinity));
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(1, 1, isoCalendar, -Infinity));
+
+const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName);
+const tests = [
+ [
+ "infinite month",
+ [O(-Infinity, "month"), O(1, "day"), () => "iso8601", O(1, "year")],
+ ["get month.valueOf", "call month.valueOf"]
+ ],
+ [
+ "infinite day",
+ [O(2, "month"), O(-Infinity, "day"), () => "iso8601", O(1, "year")],
+ ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf"]
+ ],
+ [
+ "infinite year",
+ [O(2, "month"), O(1, "day"), () => "iso8601", O(-Infinity, "year")],
+ ["get month.valueOf", "call month.valueOf", "get day.valueOf", "call day.valueOf", "get year.valueOf", "call year.valueOf"]
+ ],
+];
+
+for (const [description, args, expected] of tests) {
+ const actual = [];
+ const args_ = args.map((o) => o(actual));
+ assert.throws(RangeError, () => new Temporal.PlainMonthDay(...args_), description);
+ assert.compareArray(actual, expected, `${description} order of operations`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prop-desc.js
new file mode 100644
index 0000000000..188bbdd371
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday
+description: The "PlainMonthDay" property of Temporal
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay,
+ "function",
+ "`typeof PlainMonthDay` is `function`"
+);
+
+verifyProperty(Temporal, "PlainMonthDay", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/branding.js
new file mode 100644
index 0000000000..74a0c2a4e9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/branding.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-get-temporal.plainmonthday.prototype.calendarid
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const calendarId = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "calendarId").get;
+
+assert.sameValue(typeof calendarId, "function");
+
+assert.throws(TypeError, () => calendarId.call(undefined), "undefined");
+assert.throws(TypeError, () => calendarId.call(null), "null");
+assert.throws(TypeError, () => calendarId.call(true), "true");
+assert.throws(TypeError, () => calendarId.call(""), "empty string");
+assert.throws(TypeError, () => calendarId.call(Symbol()), "symbol");
+assert.throws(TypeError, () => calendarId.call(1), "1");
+assert.throws(TypeError, () => calendarId.call({}), "plain object");
+assert.throws(TypeError, () => calendarId.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => calendarId.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..1fe0649322
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.calendarid
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const idOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id");
+Object.defineProperty(Temporal.Calendar.prototype, "id", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("id should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.calendarId;
+
+Object.defineProperty(Temporal.Calendar.prototype, "id", idOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/prop-desc.js
new file mode 100644
index 0000000000..fb309473a0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/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.plainmonthday.prototype.calendarid
+description: The "calendarId" property of Temporal.PlainMonthDay.prototype
+features: [Temporal]
+---*/
+
+const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "calendarId");
+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/PlainMonthDay/prototype/calendarId/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/calendarId/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/constructor.js
new file mode 100644
index 0000000000..e6dd5b96f0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.constructor
+description: Test for Temporal.PlainMonthDay.prototype.constructor.
+info: The initial value of Temporal.PlainMonthDay.prototype.constructor is %Temporal.PlainMonthDay%.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "constructor", {
+ value: Temporal.PlainMonthDay,
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js
new file mode 100644
index 0000000000..14c591421e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/basic.js
@@ -0,0 +1,14 @@
+// |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.plainmonthday.prototype.day
+description: Basic tests for day().
+features: [Temporal]
+---*/
+
+const md = new Temporal.PlainMonthDay(1, 15);
+assert.sameValue(md.day, 15);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/branding.js
new file mode 100644
index 0000000000..b768a31458
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/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-get-temporal.plainmonthday.prototype.day
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const day = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "day").get;
+
+assert.sameValue(typeof day, "function");
+
+assert.throws(TypeError, () => day.call(undefined), "undefined");
+assert.throws(TypeError, () => day.call(null), "null");
+assert.throws(TypeError, () => day.call(true), "true");
+assert.throws(TypeError, () => day.call(""), "empty string");
+assert.throws(TypeError, () => day.call(Symbol()), "symbol");
+assert.throws(TypeError, () => day.call(1), "1");
+assert.throws(TypeError, () => day.call({}), "plain object");
+assert.throws(TypeError, () => day.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => day.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..d678a6ccb0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.day
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const dayOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "day");
+Object.defineProperty(Temporal.Calendar.prototype, "day", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("day should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.day;
+
+Object.defineProperty(Temporal.Calendar.prototype, "day", dayOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/custom.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/custom.js
new file mode 100644
index 0000000000..bf7cc6885f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/custom.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-get-temporal.plainmonthday.prototype.day
+description: Custom calendar tests for day().
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+let calls = 0;
+class CustomCalendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+ day(...args) {
+ ++calls;
+ assert.compareArray(args, [instance], "day arguments");
+ return 7;
+ }
+}
+
+const calendar = new CustomCalendar();
+const instance = new Temporal.PlainMonthDay(8, 25, calendar);
+const result = instance.day;
+assert.sameValue(result, 7, "result");
+assert.sameValue(calls, 1, "calls");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/prop-desc.js
new file mode 100644
index 0000000000..ab9c5cda48
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/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.plainmonthday.prototype.day
+description: The "day" property of Temporal.PlainMonthDay.prototype
+features: [Temporal]
+---*/
+
+const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "day");
+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/PlainMonthDay/prototype/day/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/validate-calendar-value.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/validate-calendar-value.js
new file mode 100644
index 0000000000..ff8cf239f9
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/day/validate-calendar-value.js
@@ -0,0 +1,41 @@
+// |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-get-temporal.plainmonthday.prototype.day
+description: Validate result returned from calendar day() method
+features: [Temporal]
+---*/
+
+const badResults = [
+ [undefined, TypeError],
+ [null, TypeError],
+ [false, TypeError],
+ [Infinity, RangeError],
+ [-Infinity, RangeError],
+ [NaN, RangeError],
+ [-7, RangeError],
+ [-0.1, RangeError],
+ ["string", TypeError],
+ [Symbol("foo"), TypeError],
+ [7n, TypeError],
+ [{}, TypeError],
+ [true, TypeError],
+ [7.1, RangeError],
+ ["7", TypeError],
+ ["7.5", TypeError],
+ [{valueOf() { return 7; }}, TypeError],
+];
+
+badResults.forEach(([result, error]) => {
+ const calendar = new class extends Temporal.Calendar {
+ day() {
+ return result;
+ }
+ }("iso8601");
+ const instance = new Temporal.PlainMonthDay(12, 15, calendar);
+ assert.throws(error, () => instance.day, `${typeof result} ${String(result)} not converted to positive integer`);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..67167d5a8f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+const arg = { monthCode: "M11", day: 23, calendar: "iso8601" };
+instance.equals(arg);
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-number.js
new file mode 100644
index 0000000000..0edd0b0d6b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: A number is invalid in place of an ISO string for Temporal.PlainMonthDay
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+const numbers = [
+ 1,
+ 1118,
+ -1118,
+ 12345,
+];
+
+for (const arg of numbers) {
+ assert.throws(
+ TypeError,
+ () => instance.equals(arg),
+ `A number (${arg}) is not a valid ISO string for PlainMonthDay`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-case-insensitive.js
new file mode 100644
index 0000000000..b5f54d1a21
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: The calendar name is case-insensitive
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+const calendar = "IsO8601";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = instance.equals(arg);
+assert.sameValue(result, true, "Calendar is case-insensitive");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-leap-second.js
new file mode 100644
index 0000000000..5d016eff84
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Leap second is a valid ISO string for a calendar in a property bag
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+const calendar = "2016-12-31T23:59:60";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = instance.equals(arg);
+assert.sameValue(
+ result,
+ true,
+ "leap second is a valid ISO string for calendar"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-number.js
new file mode 100644
index 0000000000..961d01e135
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: A number as calendar in a property bag is not accepted
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+const numbers = [
+ 1,
+ 19970327,
+ -19970327,
+ 1234567890,
+];
+
+for (const calendar of numbers) {
+ const arg = { monthCode: "M11", day: 18, calendar };
+ assert.throws(
+ TypeError,
+ () => instance.equals(arg),
+ "Numbers cannot be used as a calendar"
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-string.js
new file mode 100644
index 0000000000..e179d0c16a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: A calendar ID is valid input for Calendar
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+const calendar = "iso8601";
+
+const arg = { monthCode: "M11", day: 18, calendar };
+const result = instance.equals(arg);
+assert.sameValue(result, true, `Calendar created from string "${calendar}"`);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-wrong-type.js
new file mode 100644
index 0000000000..d35d114766
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+
+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.equals(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.equals(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/PlainMonthDay/prototype/equals/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-propertybag-calendar-year-zero.js
new file mode 100644
index 0000000000..e3303ba1f5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-calendar-annotation.js
new file mode 100644
index 0000000000..5378f5e7d5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Various forms of calendar annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[u-ca=iso8601]", "without time zone"],
+ ["1976-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"],
+ ["1976-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"],
+ ["1976-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"],
+ ["1976-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"],
+];
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+tests.forEach(([arg, description]) => {
+ const result = instance.equals(arg);
+
+ assert.sameValue(
+ result,
+ true,
+ `calendar annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-critical-unknown-annotation.js
new file mode 100644
index 0000000000..9759457bfe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ `reject unknown annotation with critical flag: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-date-with-utc-offset.js
new file mode 100644
index 0000000000..da63cbceda
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-date-with-utc-offset.js
@@ -0,0 +1,64 @@
+// |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.plainmonthday.prototype.equals
+description: UTC offset not valid with format that does not include a time
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+const validStrings = [
+ "05-02[Asia/Katmandu]",
+ "05-02[!Asia/Katmandu]",
+ "05-02[u-ca=iso8601]",
+ "05-02[Asia/Tokyo][u-ca=iso8601]",
+ "--05-02[Asia/Katmandu]",
+ "--05-02[!Asia/Katmandu]",
+ "--05-02[u-ca=iso8601]",
+ "--05-02[Asia/Tokyo][u-ca=iso8601]",
+ "2000-05-02T00+00:00",
+ "2000-05-02T00+00:00[UTC]",
+ "2000-05-02T00-02:30[America/St_Johns]",
+];
+
+for (const arg of validStrings) {
+ const result = instance.equals(arg);
+
+ assert.sameValue(
+ result,
+ true,
+ `"${arg}" is a valid UTC offset with time for PlainMonthDay`
+ );
+}
+
+const invalidStrings = [
+ "09-15Z",
+ "09-15Z[UTC]",
+ "09-15+01:00",
+ "09-15+01:00[Europe/Vienna]",
+ "--09-15Z",
+ "--09-15Z[UTC]",
+ "--09-15+01:00",
+ "--09-15+01:00[Europe/Vienna]",
+ "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]",
+ "09-15[u-ca=chinese]",
+];
+
+for (const arg of invalidStrings) {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ `"${arg}" UTC offset without time is not valid for PlainMonthDay`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-invalid.js
new file mode 100644
index 0000000000..43a0d89fe6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-invalid.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.plainmonthday.prototype.equals
+description: An invalid ISO string is never supported
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(11, 18);
+
+for (const arg of TemporalHelpers.ISO.plainMonthDayStringsInvalid()) {
+ assert.throws(RangeError, () => instance.equals(arg), `"${arg}" is not a valid PlainMonthDay string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-calendar.js
new file mode 100644
index 0000000000..d32bc2f4c2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ `reject more than one calendar annotation if any critical: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-multiple-time-zone.js
new file mode 100644
index 0000000000..23be236348
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ `reject more than one time zone annotation: ${arg}`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-separators.js
new file mode 100644
index 0000000000..098c82328e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Time separator in string argument can vary
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23", "uppercase T"],
+ ["1976-05-02t15:23", "lowercase T"],
+ ["1976-05-02 15:23", "space between date and time"],
+];
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+tests.forEach(([arg, description]) => {
+ const result = instance.equals(arg);
+
+ assert.sameValue(
+ result,
+ true,
+ `variant time separators (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-time-zone-annotation.js
new file mode 100644
index 0000000000..29cfc962a0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Various forms of time zone annotation; critical flag has no effect
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[Asia/Kolkata]", "named, with no offset"],
+ ["1976-05-02T15:23[!Europe/Vienna]", "named, with ! and no offset"],
+ ["1976-05-02T15:23[+00:00]", "numeric, with no offset"],
+ ["1976-05-02T15:23[!-02:30]", "numeric, with ! and no offset"],
+ ["1976-05-02T15:23+00:00[UTC]", "named, with offset"],
+ ["1976-05-02T15:23+00:00[!Africa/Abidjan]", "named, with offset and !"],
+ ["1976-05-02T15:23+00:00[+01:00]", "numeric, with offset"],
+ ["1976-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"],
+];
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+tests.forEach(([arg, description]) => {
+ const result = instance.equals(arg);
+
+ assert.sameValue(
+ result,
+ true,
+ `time zone annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-unknown-annotation.js
new file mode 100644
index 0000000000..72b91aa884
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Various forms of unknown annotation
+features: [Temporal]
+---*/
+
+const tests = [
+ ["1976-05-02T15:23[foo=bar]", "alone"],
+ ["1976-05-02T15:23[UTC][foo=bar]", "with time zone"],
+ ["1976-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"],
+ ["1976-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"],
+ ["1976-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"],
+];
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+tests.forEach(([arg, description]) => {
+ const result = instance.equals(arg);
+
+ assert.sameValue(
+ result,
+ true,
+ `unknown annotation (${description})`
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string-with-utc-designator.js
new file mode 100644
index 0000000000..87c198701d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: RangeError thrown if a string with UTC designator is used as a PlainMonthDay
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "2019-10-01T09:00:00Z",
+ "2019-10-01T09:00:00Z[UTC]",
+];
+const instance = new Temporal.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ "String with UTC designator should not be valid as a PlainMonthDay"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-string.js
new file mode 100644
index 0000000000..ad0d64601f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-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.plainmonthday.prototype.equals
+description: A string argument is parsed into a PlainMonthDay
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(10, 1);
+for (const arg of TemporalHelpers.ISO.plainMonthDayStringsValid()) {
+ const result = instance.equals(arg);
+ assert.sameValue(result, true, `"${arg}" is a valid PlainMonthDay string`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/argument-wrong-type.js
new file mode 100644
index 0000000000..90cbf16040
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: >
+ Appropriate error thrown when argument cannot be converted to a valid string
+ or property bag for PlainMonthDay
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+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.equals(arg),
+ `${description} does not convert to a valid ISO string`
+ );
+}
+
+const typeErrorTests = [
+ [Symbol(), "symbol"],
+ [{}, "plain object"],
+ [Temporal.PlainMonthDay, "Temporal.PlainMonthDay, object"],
+ [Temporal.PlainMonthDay.prototype, "Temporal.PlainMonthDay.prototype, object"],
+];
+
+for (const [arg, description] of typeErrorTests) {
+ assert.throws(TypeError, () => instance.equals(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/PlainMonthDay/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.js
new file mode 100644
index 0000000000..d79e487636
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/basic.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.plainmonthday.prototype.equals
+description: Basic tests for equals()
+features: [Temporal]
+---*/
+
+const md1 = Temporal.PlainMonthDay.from("01-22");
+const md2 = Temporal.PlainMonthDay.from("12-15");
+assert(md1.equals(md1), "same object");
+assert.sameValue(md1.equals(md2), false, "different object");
+
+assert(md1.equals("01-22"), "same string");
+assert.sameValue(md2.equals("01-22"), false, "different string");
+
+assert(md1.equals({ month: 1, day: 22 }), "same property bag");
+assert.sameValue(md2.equals({ month: 1, day: 22 }), false, "different property bag");
+
+assert.throws(TypeError, () => md1.equals({ month: 1 }), "missing field in property bag");
+
+const mdYear1 = new Temporal.PlainMonthDay(1, 1, undefined, 1972);
+const mdYear2 = new Temporal.PlainMonthDay(1, 1, undefined, 2000);
+assert.sameValue(mdYear1.equals(mdYear2), false, "different reference years");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/branding.js
new file mode 100644
index 0000000000..f89a12072c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const equals = Temporal.PlainMonthDay.prototype.equals;
+
+assert.sameValue(typeof equals, "function");
+
+const args = [new Temporal.PlainMonthDay(5, 2)];
+
+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.PlainMonthDay, args), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => equals.apply(Temporal.PlainMonthDay.prototype, args), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..20adcbcc08
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.equals
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const idOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id");
+Object.defineProperty(Temporal.Calendar.prototype, "id", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("id should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.equals(new Temporal.PlainMonthDay(5, 2));
+
+Object.defineProperty(Temporal.Calendar.prototype, "id", idOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/builtin.js
new file mode 100644
index 0000000000..933acb1ba0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: >
+ Tests that Temporal.PlainMonthDay.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.PlainMonthDay.prototype.equals),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.equals),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.equals),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.equals.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-datefromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..79a43e3676
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: >
+ Calendar.monthDayFromFields method is called with a null-prototype fields object
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
+const instance = new Temporal.PlainMonthDay(5, 2);
+const arg = { monthCode: "M05", day: 2, calendar };
+instance.equals(arg);
+assert.sameValue(calendar.monthDayFromFieldsCallCount, 1, "monthDayFromFields should be called on the property bag's calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.js
new file mode 100644
index 0000000000..4d0ed1c81d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-fields-iterable.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.plainmonthday.prototype.equals
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.plainmonthday.prototype.equals step 3:
+ 3. Set _other_ to ? ToTemporalMonthDay(_other_).
+ sec-temporal-totemporalmonthday step 2.f:
+ f. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
+ sec-temporal-calendarfields step 4:
+ 4. Let _result_ be ? IterableToList(_fieldsArray_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "day",
+ "month",
+ "monthCode",
+ "year",
+];
+
+const calendar1 = TemporalHelpers.calendarFieldsIterable();
+const date = new Temporal.PlainMonthDay(5, 2, calendar1);
+const calendar2 = TemporalHelpers.calendarFieldsIterable();
+date.equals({ monthCode: "M06", day: 2, calendar: calendar2 });
+
+assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called");
+assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once");
+assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args");
+assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js
new file mode 100644
index 0000000000..755b1d76a5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.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.plainmonthday.prototype.equals
+description: >
+ Calendar.monthDayFromFields method is called with undefined as the options
+ value when call originates internally
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions();
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+instance.equals({ monthCode: "M05", day: 3, calendar });
+assert.sameValue(calendar.monthDayFromFieldsCallCount, 1);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-temporal-object.js
new file mode 100644
index 0000000000..49c57643d0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
+info: |
+ sec-temporal.plainmonthday.prototype.equals step 3:
+ 3. Set _other_ to ? ToTemporalMonthDay(_other_).
+ sec-temporal-totemporalmonthday step 3.e:
+ e. 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 monthday = new Temporal.PlainMonthDay(5, 2, temporalObject);
+ monthday.equals({ monthCode: "M06", day: 2, calendar: temporalObject });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js
new file mode 100644
index 0000000000..8061c9fd53
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/calendars.js
@@ -0,0 +1,55 @@
+// |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.plainmonthday.prototype.equals
+description: Basic tests for equals() calendar handling
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get calendar a.id",
+ "get calendar b.id",
+];
+const actual = [];
+const calendar = (id) => {
+ const c = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+ };
+ TemporalHelpers.observeProperty(actual, c, "id", id, `calendar ${id}`);
+ return c;
+};
+
+const mdA = new Temporal.PlainMonthDay(2, 7, calendar("a"));
+const mdB = new Temporal.PlainMonthDay(2, 7, calendar("b"));
+const mdC = new Temporal.PlainMonthDay(2, 7, calendar("c"), 1974);
+actual.splice(0); // disregard the HasProperty checks done in the constructor
+
+assert.sameValue(mdA.equals(mdC), false, "different year");
+assert.compareArray(actual, [], "Should not check calendar");
+
+assert.sameValue(mdA.equals(mdB), false, "different calendar");
+assert.compareArray(actual, expected, "Should check calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..762ba80f78
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2, calendar);
+
+assert.throws(RangeError, () => instance.equals(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..dd58ceb4c5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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'], ['month'], ['monthCode'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar };
+ const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+
+ assert.throws(RangeError, () => instance.equals(arg));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..a57a03b825
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+const base = { year: 2000, month: 5, day: 2 };
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["year", "month", "day"].forEach((prop) => {
+ assert.throws(RangeError, () => instance.equals({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
+ assert.throws(RangeError, () => instance.equals({ ...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/PlainMonthDay/prototype/equals/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/leap-second.js
new file mode 100644
index 0000000000..6fbc596406
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Leap second is a valid ISO string for PlainMonthDay
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(12, 31);
+
+let arg = "2016-12-31T23:59:60";
+const result1 = instance.equals(arg);
+assert.sameValue(
+ result1,
+ true,
+ "leap second is a valid ISO string for PlainMonthDay"
+);
+
+arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
+const result2 = instance.equals(arg);
+assert.sameValue(
+ result2,
+ true,
+ "second: 60 is ignored in property bag for PlainMonthDay"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/length.js
new file mode 100644
index 0000000000..04d789a98a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.equals, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/name.js
new file mode 100644
index 0000000000..57f153ee91
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.equals, "name", {
+ value: "equals",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/not-a-constructor.js
new file mode 100644
index 0000000000..6ca09f5c77
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: >
+ Temporal.PlainMonthDay.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.PlainMonthDay.prototype.equals();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.equals), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.equals)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/prop-desc.js
new file mode 100644
index 0000000000..52ba3afee2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: The "equals" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.equals,
+ "function",
+ "`typeof PlainMonthDay.prototype.equals` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "equals", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..6530f40ac1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+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.PlainMonthDay(5, 2, calendar);
+
+assert.throws(RangeError, () => instance.equals(arg));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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/PlainMonthDay/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/year-zero.js
new file mode 100644
index 0000000000..bfe6d361df
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/equals/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.plainmonthday.prototype.equals
+description: Negative zero, as an extended year, is rejected
+features: [Temporal, arrow-function]
+---*/
+
+const invalidStrings = [
+ "-000000-08-24",
+ "-000000-08-24T15:43:27",
+ "-000000-08-24T15:43:27+01:00",
+ "-000000-08-24T15:43:27+00:00[UTC]",
+];
+const instance = new Temporal.PlainMonthDay(5, 2);
+invalidStrings.forEach((arg) => {
+ assert.throws(
+ RangeError,
+ () => instance.equals(arg),
+ "reject minus zero as extended year"
+ );
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/branding.js
new file mode 100644
index 0000000000..fa1039773b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/branding.js
@@ -0,0 +1,25 @@
+// |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.plainmonthday.prototype.getcalendar
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getCalendar = Temporal.PlainMonthDay.prototype.getCalendar;
+
+assert.sameValue(typeof getCalendar, "function");
+
+assert.throws(TypeError, () => getCalendar.call(undefined), "undefined");
+assert.throws(TypeError, () => getCalendar.call(null), "null");
+assert.throws(TypeError, () => getCalendar.call(true), "true");
+assert.throws(TypeError, () => getCalendar.call(""), "empty string");
+assert.throws(TypeError, () => getCalendar.call(Symbol()), "symbol");
+assert.throws(TypeError, () => getCalendar.call(1), "1");
+assert.throws(TypeError, () => getCalendar.call({}), "plain object");
+assert.throws(TypeError, () => getCalendar.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => getCalendar.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/builtin.js
new file mode 100644
index 0000000000..eaf4f5272a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/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.plainmonthday.prototype.getcalendar
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.getCalendar
+ 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.PlainMonthDay.prototype.getCalendar),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.getCalendar),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.getCalendar),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.getCalendar.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/length.js
new file mode 100644
index 0000000000..089c7aef96
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/length.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.plainmonthday.prototype.getcalendar
+description: Temporal.PlainMonthDay.prototype.getCalendar.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.PlainMonthDay.prototype.getCalendar, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/name.js
new file mode 100644
index 0000000000..00adc34b54
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/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.plainmonthday.prototype.getcalendar
+description: Temporal.PlainMonthDay.prototype.getCalendar.name is "getCalendar".
+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.PlainMonthDay.prototype.getCalendar, "name", {
+ value: "getCalendar",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/not-a-constructor.js
new file mode 100644
index 0000000000..e33dee0c53
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/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.plainmonthday.prototype.getcalendar
+description: >
+ Temporal.PlainMonthDay.prototype.getCalendar 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.PlainMonthDay.prototype.getCalendar();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.getCalendar), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.getCalendar)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/prop-desc.js
new file mode 100644
index 0000000000..35510b6103
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/prop-desc.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.plainmonthday.prototype.getcalendar
+description: The "getCalendar" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.getCalendar,
+ "function",
+ "`typeof PlainMonthDay.prototype.getCalendar` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "getCalendar", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getCalendar/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/PlainMonthDay/prototype/getISOFields/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/branding.js
new file mode 100644
index 0000000000..ecae88abce
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/branding.js
@@ -0,0 +1,25 @@
+// |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.plainmonthday.prototype.getisofields
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const getISOFields = Temporal.PlainMonthDay.prototype.getISOFields;
+
+assert.sameValue(typeof getISOFields, "function");
+
+assert.throws(TypeError, () => getISOFields.call(undefined), "undefined");
+assert.throws(TypeError, () => getISOFields.call(null), "null");
+assert.throws(TypeError, () => getISOFields.call(true), "true");
+assert.throws(TypeError, () => getISOFields.call(""), "empty string");
+assert.throws(TypeError, () => getISOFields.call(Symbol()), "symbol");
+assert.throws(TypeError, () => getISOFields.call(1), "1");
+assert.throws(TypeError, () => getISOFields.call({}), "plain object");
+assert.throws(TypeError, () => getISOFields.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => getISOFields.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/builtin.js
new file mode 100644
index 0000000000..b59a73f8fe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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.plainmonthday.prototype.getisofields
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.getISOFields
+ 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.PlainMonthDay.prototype.getISOFields),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.getISOFields),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.getISOFields),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.getISOFields.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/custom.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/custom.js
new file mode 100644
index 0000000000..ecba8614f1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/custom.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.plainmonthday.prototype.getisofields
+description: getISOFields does not call into user code.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarThrowEverything();
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+const result = instance.getISOFields();
+
+assert.sameValue(result.isoYear, 1972, "isoYear result");
+assert.sameValue(result.isoMonth, 5, "isoMonth result");
+assert.sameValue(result.isoDay, 2, "isoDay result");
+assert.sameValue(result.calendar, calendar, "calendar result");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.js
new file mode 100644
index 0000000000..c481143d62
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-names.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.plainmonthday.prototype.getisofields
+description: Correct field names on the object returned from getISOFields
+features: [Temporal]
+---*/
+
+const md = new Temporal.PlainMonthDay(5, 2);
+
+const result = md.getISOFields();
+assert.sameValue(result.isoYear, 1972, "isoYear result");
+assert.sameValue(result.isoMonth, 5, "isoMonth result");
+assert.sameValue(result.isoDay, 2, "isoDay result");
+assert.sameValue(result.calendar, "iso8601", "calendar result");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js
new file mode 100644
index 0000000000..0661e29f4a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-prop-desc.js
@@ -0,0 +1,30 @@
+// |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.plainmonthday.prototype.getisofields
+description: Properties on the returned object have the correct descriptor
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "calendar",
+ "isoDay",
+ "isoMonth",
+ "isoYear",
+];
+
+const md = new Temporal.PlainMonthDay(5, 2);
+const result = md.getISOFields();
+
+for (const property of expected) {
+ verifyProperty(result, property, {
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ });
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.js
new file mode 100644
index 0000000000..57addcf0dc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/field-traversal-order.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.plainmonthday.prototype.getisofields
+description: Properties added in correct order to object returned from getISOFields
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "calendar",
+ "isoDay",
+ "isoMonth",
+ "isoYear",
+];
+
+const md = new Temporal.PlainMonthDay(5, 2);
+const result = md.getISOFields();
+
+assert.compareArray(Object.keys(result), expected);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/length.js
new file mode 100644
index 0000000000..f354e5eba6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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.plainmonthday.prototype.getisofields
+description: Temporal.PlainMonthDay.prototype.getISOFields.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.PlainMonthDay.prototype.getISOFields, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/name.js
new file mode 100644
index 0000000000..531f0e1f29
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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.plainmonthday.prototype.getisofields
+description: Temporal.PlainMonthDay.prototype.getISOFields.name is "getISOFields".
+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.PlainMonthDay.prototype.getISOFields, "name", {
+ value: "getISOFields",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/not-a-constructor.js
new file mode 100644
index 0000000000..476aef139d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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.plainmonthday.prototype.getisofields
+description: >
+ Temporal.PlainMonthDay.prototype.getISOFields 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.PlainMonthDay.prototype.getISOFields();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.getISOFields), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.getISOFields)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prop-desc.js
new file mode 100644
index 0000000000..972010131e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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.plainmonthday.prototype.getisofields
+description: The "getISOFields" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.getISOFields,
+ "function",
+ "`typeof PlainMonthDay.prototype.getISOFields` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "getISOFields", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prototype.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prototype.js
new file mode 100644
index 0000000000..f3708b4c11
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/prototype.js
@@ -0,0 +1,15 @@
+// |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.plainmonthday.prototype.getisofields
+description: Correct prototype on the object returned from getISOFields
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+const result = instance.getISOFields();
+assert.sameValue(Object.getPrototypeOf(result), Object.prototype, "prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/getISOFields/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/PlainMonthDay/prototype/month/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js
new file mode 100644
index 0000000000..1ec10c467c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/month/unsupported.js
@@ -0,0 +1,15 @@
+// |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.plainmonthday.prototype.monthcode
+description: There is no 'month' property on Temporal.PlainMonthDay
+features: [Temporal]
+---*/
+
+const md = new Temporal.PlainMonthDay(1, 15);
+assert.sameValue(md.month, undefined);
+assert.sameValue("month" in md, false);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js
new file mode 100644
index 0000000000..5734f9d292
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/basic.js
@@ -0,0 +1,14 @@
+// |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.plainmonthday.prototype.monthcode
+description: Basic tests for monthCode().
+features: [Temporal]
+---*/
+
+const md = new Temporal.PlainMonthDay(1, 15);
+assert.sameValue(md.monthCode, "M01");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/branding.js
new file mode 100644
index 0000000000..71d03f49a4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/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-get-temporal.plainmonthday.prototype.monthcode
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const monthCode = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "monthCode").get;
+
+assert.sameValue(typeof monthCode, "function");
+
+assert.throws(TypeError, () => monthCode.call(undefined), "undefined");
+assert.throws(TypeError, () => monthCode.call(null), "null");
+assert.throws(TypeError, () => monthCode.call(true), "true");
+assert.throws(TypeError, () => monthCode.call(""), "empty string");
+assert.throws(TypeError, () => monthCode.call(Symbol()), "symbol");
+assert.throws(TypeError, () => monthCode.call(1), "1");
+assert.throws(TypeError, () => monthCode.call({}), "plain object");
+assert.throws(TypeError, () => monthCode.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => monthCode.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..a8d85ef241
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.monthcode
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const monthCodeOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "monthCode");
+Object.defineProperty(Temporal.Calendar.prototype, "monthCode", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("monthCode should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.monthCode;
+
+Object.defineProperty(Temporal.Calendar.prototype, "monthCode", monthCodeOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/custom.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/custom.js
new file mode 100644
index 0000000000..ad54832ccd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/custom.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-get-temporal.plainmonthday.prototype.monthcode
+description: Custom calendar tests for monthCode().
+includes: [compareArray.js]
+features: [Temporal]
+---*/
+
+let calls = 0;
+class CustomCalendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+ monthCode(...args) {
+ ++calls;
+ assert.compareArray(args, [instance], "monthCode arguments");
+ return "M01";
+ }
+}
+
+const calendar = new CustomCalendar();
+const instance = new Temporal.PlainMonthDay(8, 25, calendar);
+const result = instance.monthCode;
+assert.sameValue(result, "M01", "result");
+assert.sameValue(calls, 1, "calls");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/prop-desc.js
new file mode 100644
index 0000000000..447cb731af
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/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.plainmonthday.prototype.monthcode
+description: The "monthCode" property of Temporal.PlainMonthDay.prototype
+features: [Temporal]
+---*/
+
+const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainMonthDay.prototype, "monthCode");
+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/PlainMonthDay/prototype/monthCode/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/validate-calendar-value.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/validate-calendar-value.js
new file mode 100644
index 0000000000..a21782ab1a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/monthCode/validate-calendar-value.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-get-temporal.plainmonthday.prototype.monthcode
+description: Validate result returned from calendar monthCode() method
+features: [Temporal]
+---*/
+
+const badResults = [
+ [undefined, TypeError],
+ [Symbol("foo"), TypeError],
+ [null, TypeError],
+ [true, TypeError],
+ [false, TypeError],
+ [7.1, TypeError],
+ [{toString() { return "M01"; }}, TypeError],
+];
+
+badResults.forEach(([result, error]) => {
+ const calendar = new class extends Temporal.Calendar {
+ monthCode() {
+ return result;
+ }
+ }("iso8601");
+ const instance = new Temporal.PlainMonthDay(12, 15, calendar);
+ assert.throws(error, () => instance.monthCode, `${typeof result} ${String(result)} not converted to string`);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/prop-desc.js
new file mode 100644
index 0000000000..c3502f6633
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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-plainmonthday-prototype
+description: The "prototype" property of Temporal.PlainMonthDay
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(typeof Temporal.PlainMonthDay.prototype, "object");
+assert.notSameValue(Temporal.PlainMonthDay.prototype, null);
+
+verifyProperty(Temporal.PlainMonthDay, "prototype", {
+ writable: false,
+ enumerable: false,
+ configurable: false,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/branding.js
new file mode 100644
index 0000000000..7af9f87d07
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toJSON = Temporal.PlainMonthDay.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.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => toJSON.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..ad02a34dbc
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.tojson
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const idOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id");
+Object.defineProperty(Temporal.Calendar.prototype, "id", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("id should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.toJSON();
+
+Object.defineProperty(Temporal.Calendar.prototype, "id", idOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/builtin.js
new file mode 100644
index 0000000000..5a44848034
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: >
+ Tests that Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toJSON),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toJSON),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toJSON),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.toJSON.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js
new file mode 100644
index 0000000000..1993c9aeb8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/calendarname.js
@@ -0,0 +1,54 @@
+// |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.plainmonthday.protoype.tojson
+description: toJSON doesn't take calendarName into account.
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "05-02"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[u-ca=custom]"],
+ [[{ id: "iso8601", ...calendarMethods }], "05-02"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[u-ca=ISO8601]"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i
+];
+const options = {
+ get calendarName() {
+ TemporalHelpers.assertUnreachable("calendarName should not be accessed");
+ return "";
+ }
+};
+
+for (const [args, expected] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toJSON(options);
+ assert.sameValue(result, expected);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/length.js
new file mode 100644
index 0000000000..40bb95be1e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toJSON, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/name.js
new file mode 100644
index 0000000000..99f0a89d16
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toJSON, "name", {
+ value: "toJSON",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/not-a-constructor.js
new file mode 100644
index 0000000000..22a801c92c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: >
+ Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toJSON();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toJSON), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.toJSON)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/prop-desc.js
new file mode 100644
index 0000000000..73fafdab26
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tojson
+description: The "toJSON" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.toJSON,
+ "function",
+ "`typeof PlainMonthDay.prototype.toJSON` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "toJSON", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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/PlainMonthDay/prototype/toJSON/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js
new file mode 100644
index 0000000000..9a9cca8e1d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js
@@ -0,0 +1,58 @@
+// |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.plainmonthday.prototype.tojson
+description: Verify that the year is appropriately formatted as 4 or 6 digits
+features: [Temporal]
+---*/
+
+// For PlainMonthDay, the ISO reference year is only present in the string if
+// the calendar is not ISO 8601
+class NotISO extends Temporal.Calendar {
+ constructor() { super("iso8601"); }
+ get id() { return "not-iso"; }
+}
+const calendar = new NotISO();
+
+let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000);
+assert.sameValue(instance.toJSON(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000);
+assert.sameValue(instance.toJSON(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999);
+assert.sameValue(instance.toJSON(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000);
+assert.sameValue(instance.toJSON(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(10, 9, calendar, -999);
+assert.sameValue(instance.toJSON(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 7, calendar, -1);
+assert.sameValue(instance.toJSON(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(6, 5, calendar, 0);
+assert.sameValue(instance.toJSON(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(4, 3, calendar, 1);
+assert.sameValue(instance.toJSON(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(2, 10, calendar, 999);
+assert.sameValue(instance.toJSON(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000);
+assert.sameValue(instance.toJSON(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999);
+assert.sameValue(instance.toJSON(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000);
+assert.sameValue(instance.toJSON(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000);
+assert.sameValue(instance.toJSON(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/branding.js
new file mode 100644
index 0000000000..5d7b968e7c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toLocaleString = Temporal.PlainMonthDay.prototype.toLocaleString;
+
+assert.sameValue(typeof toLocaleString, "function");
+
+assert.throws(TypeError, () => toLocaleString.call(undefined), "undefined");
+assert.throws(TypeError, () => toLocaleString.call(null), "null");
+assert.throws(TypeError, () => toLocaleString.call(true), "true");
+assert.throws(TypeError, () => toLocaleString.call(""), "empty string");
+assert.throws(TypeError, () => toLocaleString.call(Symbol()), "symbol");
+assert.throws(TypeError, () => toLocaleString.call(1), "1");
+assert.throws(TypeError, () => toLocaleString.call({}), "plain object");
+assert.throws(TypeError, () => toLocaleString.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => toLocaleString.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..90bc4675de
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.tolocalestring
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const idOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id");
+Object.defineProperty(Temporal.Calendar.prototype, "id", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("id should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.toLocaleString(undefined, { calendar: "iso8601" });
+
+Object.defineProperty(Temporal.Calendar.prototype, "id", idOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/builtin.js
new file mode 100644
index 0000000000..8ecfbca8e5
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.toLocaleString
+ 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.PlainMonthDay.prototype.toLocaleString),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toLocaleString),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toLocaleString),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.toLocaleString.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/length.js
new file mode 100644
index 0000000000..5e31fdccdb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: Temporal.PlainMonthDay.prototype.toLocaleString.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.PlainMonthDay.prototype.toLocaleString, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/name.js
new file mode 100644
index 0000000000..5a326d9fa8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: Temporal.PlainMonthDay.prototype.toLocaleString.name is "toLocaleString".
+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.PlainMonthDay.prototype.toLocaleString, "name", {
+ value: "toLocaleString",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/not-a-constructor.js
new file mode 100644
index 0000000000..a295107962
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: >
+ Temporal.PlainMonthDay.prototype.toLocaleString 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.PlainMonthDay.prototype.toLocaleString();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toLocaleString), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.toLocaleString)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/prop-desc.js
new file mode 100644
index 0000000000..0a03647176
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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.plainmonthday.prototype.tolocalestring
+description: The "toLocaleString" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.toLocaleString,
+ "function",
+ "`typeof PlainMonthDay.prototype.toLocaleString` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "toLocaleString", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toLocaleString/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/PlainMonthDay/prototype/toPlainDate/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.js
new file mode 100644
index 0000000000..66e4537b18
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/argument-not-object.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.plainmonthday.prototype.toplaindate
+description: Throws a TypeError if the argument is not an Object, before any other observable actions
+includes: [compareArray.js, temporalHelpers.js]
+features: [BigInt, Symbol, Temporal]
+---*/
+
+[null, undefined, true, 3.1416, "a string", Symbol("symbol"), 7n].forEach((primitive) => {
+ const calendar = TemporalHelpers.calendarThrowEverything();
+ const plainMonthDay = new Temporal.PlainMonthDay(5, 2, calendar);
+ assert.throws(TypeError, () => plainMonthDay.toPlainDate(primitive));
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.js
new file mode 100644
index 0000000000..66501b5d14
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/basic.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.plainmonthday.prototype.toplaindate
+description: Basic tests for toPlainDate().
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const md = Temporal.PlainMonthDay.from("01-22");
+const d = md.toPlainDate({ year: 2002 });
+TemporalHelpers.assertPlainDate(d, 2002, 1, "M01", 22);
+
+assert.throws(TypeError, () => md.toPlainDate({ something: 'nothing' }), "missing fields");
+
+const leapDay = Temporal.PlainMonthDay.from('02-29');
+TemporalHelpers.assertPlainDate(leapDay.toPlainDate({ year: 2020 }), 2020, 2, "M02", 29);
+
+const options = {
+ get overflow() {
+ TemporalHelpers.assertUnreachable("Should not get overflow option");
+ return "";
+ }
+};
+TemporalHelpers.assertPlainDate(leapDay.toPlainDate({ year: 2020 }, options), 2020, 2, "M02", 29);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/branding.js
new file mode 100644
index 0000000000..4fde5eb378
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toPlainDate = Temporal.PlainMonthDay.prototype.toPlainDate;
+
+assert.sameValue(typeof toPlainDate, "function");
+
+const args = [{ year: 2022 }];
+
+assert.throws(TypeError, () => toPlainDate.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => toPlainDate.apply(null, args), "null");
+assert.throws(TypeError, () => toPlainDate.apply(true, args), "true");
+assert.throws(TypeError, () => toPlainDate.apply("", args), "empty string");
+assert.throws(TypeError, () => toPlainDate.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => toPlainDate.apply(1, args), "1");
+assert.throws(TypeError, () => toPlainDate.apply({}, args), "plain object");
+assert.throws(TypeError, () => toPlainDate.apply(Temporal.PlainMonthDay, args), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => toPlainDate.apply(Temporal.PlainMonthDay.prototype, args), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..e9657f74af
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-array-iteration.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable array iteration when getting the calendar fields.
+features: [Temporal]
+---*/
+
+const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator];
+Array.prototype[Symbol.iterator] = function arrayIterator() {
+ throw new Test262Error("Array should not be iterated");
+}
+
+const instance = new Temporal.PlainMonthDay(5, 1, "iso8601");
+instance.toPlainDate({ year: 2005 });
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..7a2935df2c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin-calendar-no-observable-calls.js
@@ -0,0 +1,46 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const fieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "fields");
+Object.defineProperty(Temporal.Calendar.prototype, "fields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("fields should not be looked up");
+ },
+});
+const mergeFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "mergeFields");
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("mergeFields should not be looked up");
+ },
+});
+const dateFromFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "dateFromFields");
+Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("dateFromFields should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.toPlainDate({ year: 2002 });
+
+Object.defineProperty(Temporal.Calendar.prototype, "fields", fieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", mergeFieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", dateFromFieldsOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/builtin.js
new file mode 100644
index 0000000000..d414e7501f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.toPlainDate
+ 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.PlainMonthDay.prototype.toPlainDate),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toPlainDate),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toPlainDate),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.toPlainDate.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js
new file mode 100644
index 0000000000..1522f05f0e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fields-iterable.js
@@ -0,0 +1,37 @@
+// |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.plainmonthday.prototype.toplaindate
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.plainmonthday.prototype.toplaindate step 4:
+ 4. Let _receiverFieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"monthCode"* »).
+ sec-temporal.plainmonthday.prototype.toplaindate step 7:
+ 7. Let _inputFieldNames_ be ? CalendarFields(_calendar_, « *"year"* »).
+ sec-temporal-calendarfields step 4:
+ 4. Let _result_ be ? IterableToList(_fieldsArray_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected1 = [
+ "day",
+ "monthCode",
+];
+const expected2 = [
+ "year",
+];
+
+const calendar = TemporalHelpers.calendarFieldsIterable();
+const monthday = new Temporal.PlainMonthDay(5, 2, calendar);
+monthday.toPlainDate({ year: 1997 });
+
+assert.sameValue(calendar.fieldsCallCount, 2, "fields() method called twice");
+assert.compareArray(calendar.fieldsCalledWith[0], expected1, "fields() method called first time with correct args");
+assert.compareArray(calendar.fieldsCalledWith[1], expected2, "fields() method called second time with correct args");
+assert(calendar.iteratorExhausted[0], "iterated through the whole first iterable");
+assert(calendar.iteratorExhausted[1], "iterated through the whole second iterable");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..fb95a25ed6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-fromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+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.PlainMonthDay(5, 2, calendar);
+instance.toPlainDate({ year: 2019 });
+assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js
new file mode 100644
index 0000000000..e70303d0da
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-merge-fields-returns-primitive.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+description: >
+ with() should throw a TypeError if mergeFields() returns a primitive,
+ without passing the value on to any other calendar methods
+includes: [compareArray.js, temporalHelpers.js]
+features: [BigInt, Symbol, Temporal]
+---*/
+
+[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => {
+ const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive);
+ const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+ assert.throws(TypeError, () => instance.toPlainDate({ year: 2005 }), "bad return from mergeFields() throws");
+ assert.sameValue(calendar.dateFromFieldsCallCount, 0, "dateFromFields() never called");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-mergefields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-mergefields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..3faab87e34
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/calendar-mergefields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+description: >
+ Calendar.mergeFields method is called with null-prototype fields objects
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckMergeFieldsPrototypePollution();
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+instance.toPlainDate({ year: 2019 });
+assert.sameValue(calendar.mergeFieldsCallCount, 1, "mergeFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..ba5d3dc36f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/constructor-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+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 md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+assert.throws(RangeError, () => md.toPlainDate({year: 2023}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.js
new file mode 100644
index 0000000000..232f3b089f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/copies-merge-fields-object.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.plainmonthday.prototype.toplaindate
+description: The object returned from mergeFields() is copied before being passed to monthDayFromFields().
+info: |
+ sec-temporal.plainmonthday.prototype.toplaindate steps 9 and 11:
+ 9. Let _mergedFields_ be ? CalendarMergeFields(_calendar_, _fields_, _inputFields_).
+ 11. Set _mergedFields_ to ? PrepareTemporalFields(_mergedFields_, _mergedFieldNames_, «»).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get day",
+ "get day.valueOf",
+ "call day.valueOf",
+ "get monthCode",
+ "get monthCode.toString",
+ "call monthCode.toString",
+ "get year",
+ "get year.valueOf",
+ "call year.valueOf",
+];
+
+const calendar = TemporalHelpers.calendarMergeFieldsGetters();
+const monthday = new Temporal.PlainMonthDay(3, 31, calendar);
+monthday.toPlainDate({ year: 2000 });
+
+assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/default-overflow-behaviour.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/default-overflow-behaviour.js
new file mode 100644
index 0000000000..a5457d59af
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/default-overflow-behaviour.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-temporal.plainmonthday.prototype.toplaindate
+description: A nonexistent resulting date is constrained to an existing date
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const leapDay = new Temporal.PlainMonthDay(2, 29);
+const result = leapDay.toPlainDate({ year: 2023 });
+// 2023-02-29 does not exist because 2023 is a common year
+TemporalHelpers.assertPlainDate(result, 2023, 2, "M02", 28, "2023 + 02-29 = 2023-02-28");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..b37b1f1936
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/duplicate-calendar-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+for (const extra_fields of [['foo', 'foo'], ['monthCode'], ['day'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+ assert.throws(RangeError, () => md.toPlainDate({year: 2023}));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..3078b75827
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/infinity-throws-rangeerror.js
@@ -0,0 +1,23 @@
+// |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.
+
+/*---
+description: Throws a RangeError if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+[Infinity, -Infinity].forEach((inf) => {
+ assert.throws(RangeError, () => instance.toPlainDate({ year: inf }), `year property cannot be ${inf}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "year");
+ assert.throws(RangeError, () => instance.toPlainDate({ year: obj }));
+ assert.compareArray(calls, ["get year.valueOf", "call year.valueOf"], "it fails after fetching the primitive value");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/length.js
new file mode 100644
index 0000000000..dba010a6b6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: Temporal.PlainMonthDay.prototype.toPlainDate.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.PlainMonthDay.prototype.toPlainDate, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js
new file mode 100644
index 0000000000..232c424cde
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/limits.js
@@ -0,0 +1,33 @@
+// |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.plainmonthday.prototype.toplaindate
+description: Throws a RangeError if the resulting PlainDate is out of range
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const jan1 = Temporal.PlainMonthDay.from("01-01");
+const dec31 = Temporal.PlainMonthDay.from("12-31");
+
+const minYear = -271821;
+assert.throws(RangeError, () => jan1.toPlainDate({ year: minYear }), "jan1 min");
+const apr18 = Temporal.PlainMonthDay.from("04-18");
+assert.throws(RangeError, () => apr18.toPlainDate({ year: minYear }), "apr18 min");
+TemporalHelpers.assertPlainDate(Temporal.PlainMonthDay.from("04-19").toPlainDate({ year: minYear }),
+ minYear, 4, "M04", 19, "apr19 min");
+TemporalHelpers.assertPlainDate(jan1.toPlainDate({ year: minYear + 1 }),
+ minYear + 1, 1, "M01", 1, "jan1 min");
+
+const maxYear = 275760;
+assert.throws(RangeError, () => dec31.toPlainDate({ year: maxYear }), "dec31 max");
+const sep14 = Temporal.PlainMonthDay.from("09-14");
+assert.throws(RangeError, () => sep14.toPlainDate({ year: maxYear }), "sep14 max");
+TemporalHelpers.assertPlainDate(Temporal.PlainMonthDay.from("09-13").toPlainDate({ year: maxYear }),
+ maxYear, 9, "M09", 13, "max");
+TemporalHelpers.assertPlainDate(dec31.toPlainDate({ year: maxYear - 1 }),
+ maxYear - 1, 12, "M12", 31, "dec31 max");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/name.js
new file mode 100644
index 0000000000..4c46baa3e4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: Temporal.PlainMonthDay.prototype.toPlainDate.name is "toPlainDate".
+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.PlainMonthDay.prototype.toPlainDate, "name", {
+ value: "toPlainDate",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/not-a-constructor.js
new file mode 100644
index 0000000000..cab2fc3623
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: >
+ Temporal.PlainMonthDay.prototype.toPlainDate 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.PlainMonthDay.prototype.toPlainDate();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toPlainDate), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.toPlainDate)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/prop-desc.js
new file mode 100644
index 0000000000..270c6ee330
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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.plainmonthday.prototype.toplaindate
+description: The "toPlainDate" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.toPlainDate,
+ "function",
+ "`typeof PlainMonthDay.prototype.toPlainDate` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "toPlainDate", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..061303fea0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/proto-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.toplaindate
+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 md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+assert.throws(RangeError, () => md.toPlainDate({year: 2023}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toPlainDate/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/PlainMonthDay/prototype/toString/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/branding.js
new file mode 100644
index 0000000000..97facdb43b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const toString = Temporal.PlainMonthDay.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.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => toString.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..91f2de6b15
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin-calendar-no-observable-calls.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.plainmonthday.prototype.tostring
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const idOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id");
+Object.defineProperty(Temporal.Calendar.prototype, "id", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("id should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.toString();
+
+Object.defineProperty(Temporal.Calendar.prototype, "id", idOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/builtin.js
new file mode 100644
index 0000000000..d814aaf1ba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: >
+ Tests that Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toString),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.toString),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.toString),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.toString.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendar-tostring.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendar-tostring.js
new file mode 100644
index 0000000000..a7dc0e9195
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendar-tostring.js
@@ -0,0 +1,56 @@
+// |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.plainmonthday.protoype.tostring
+description: Number of observable 'toString' calls on the calendar for each value of calendarName
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+let calls;
+const customCalendar = {
+ get id() {
+ ++calls;
+ return "custom";
+ },
+ toString() {
+ TemporalHelpers.assertUnreachable('toString should not be called');
+ },
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+const monthday = new Temporal.PlainMonthDay(5, 2, customCalendar);
+[
+ ["always", "1972-05-02[u-ca=custom]", 1],
+ ["auto", "1972-05-02[u-ca=custom]", 1],
+ ["critical", "1972-05-02[!u-ca=custom]", 1],
+ ["never", "1972-05-02", 1],
+ [undefined, "1972-05-02[u-ca=custom]", 1],
+].forEach(([calendarName, expectedResult, expectedCalls]) => {
+ calls = 0;
+ const result = monthday.toString({ calendarName });
+ assert.sameValue(result, expectedResult, `id for calendarName = ${calendarName}`);
+ assert.sameValue(calls, expectedCalls, `calls to id getter for calendarName = ${calendarName}`);
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js
new file mode 100644
index 0000000000..75598ac80e
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.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.plainmonthday.prototype.tostring
+description: If calendarName is "always", the calendar ID should be included.
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "1972-05-02[u-ca=iso8601]", "built-in ISO"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[u-ca=custom]", "custom"],
+ [[{ id: "iso8601", ...calendarMethods }], "1972-05-02[u-ca=iso8601]", "custom with iso8601 id"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[u-ca=ISO8601]", "custom with caps id"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[u-ca=\u0131so8601]", "custom with dotless i id"],
+];
+
+for (const [args, expected, description] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toString({ calendarName: "always" });
+ assert.sameValue(result, expected, `${description} calendar for calendarName = always`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.js
new file mode 100644
index 0000000000..1ce645ffe3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-auto.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.plainmonthday.prototype.tostring
+description: If calendarName is "auto", "iso8601" should be omitted.
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "05-02", "built-in ISO"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[u-ca=custom]", "custom"],
+ [[{ id: "iso8601", ...calendarMethods }], "05-02", "custom with iso8601 id"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[u-ca=ISO8601]", "custom with caps id"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[u-ca=\u0131so8601]", "custom with dotless i id"],
+];
+
+for (const [args, expected, description] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toString({ calendarName: "auto" });
+ assert.sameValue(result, expected, `${description} calendar for calendarName = auto`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-critical.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-critical.js
new file mode 100644
index 0000000000..84832a5aae
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-critical.js
@@ -0,0 +1,50 @@
+// |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.plainmonthday.prototype.tostring
+description: >
+ If calendarName is "calendar", the calendar ID should be included and prefixed
+ with "!".
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "1972-05-02[!u-ca=iso8601]", "built-in ISO"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[!u-ca=custom]", "custom"],
+ [[{ id: "iso8601", ...calendarMethods }], "1972-05-02[!u-ca=iso8601]", "custom with iso8601 id"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[!u-ca=ISO8601]", "custom with caps id"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[!u-ca=\u0131so8601]", "custom with dotless i id"],
+];
+
+for (const [args, expected, description] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toString({ calendarName: "critical" });
+ assert.sameValue(result, expected, `${description} calendar for calendarName = critical`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..78c453b1e1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-invalid-string.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.plainmonthday.protoype.tostring
+description: RangeError thrown when calendarName 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-toshowcalendaroption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « *"string"* », « *"auto"*, *"always"*, *"never"*, *"critical"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+features: [Temporal]
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+const invalidValues = ["ALWAYS", "sometimes", "other string", "auto\0"];
+
+for (const calendarName of invalidValues) {
+ assert.throws(
+ RangeError,
+ () => monthday.toString({ calendarName }),
+ `${calendarName} is an invalid value for calendarName option`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.js
new file mode 100644
index 0000000000..c87ba6f9ed
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-never.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.plainmonthday.prototype.tostring
+description: If calendarName is "never", the calendar ID should be omitted.
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "05-02", "built-in ISO"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02", "custom"],
+ [[{ id: "iso8601", ...calendarMethods }], "05-02", "custom with iso8601 id"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02", "custom with caps id"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02", "custom with dotless i id"],
+];
+
+for (const [args, expected, description] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toString({ calendarName: "never" });
+ assert.sameValue(result, expected, `${description} calendar for calendarName = never`);
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..87f9b23051
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,56 @@
+// |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.plainmonthday.protoype.tostring
+description: Fallback value for calendarName option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-toshowcalendaroption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « *"string"* », « *"auto"*, *"always"*, *"never"*, *"critical"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "05-02", "built-in ISO"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[u-ca=custom]", "custom"],
+ [[{ id: "iso8601", ...calendarMethods }], "05-02", "custom with iso8601 id"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[u-ca=ISO8601]", "custom with caps id"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[u-ca=\u0131so8601]", "custom with dotless i id"],
+];
+
+for (const [args, expected, description] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const result = monthday.toString({ calendarName: undefined });
+ assert.sameValue(result, expected, `default calendarName option is auto with ${description} calendar`);
+ // See options-object.js for {} and options-undefined.js for absent options arg
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..6a0f7edf80
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,49 @@
+// |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.plainmonthday.protoype.tostring
+description: Type conversions for calendarName option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-toshowcalendaroption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « *"string"* », « *"auto"*, *"always"*, *"never"*, *"critical"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = {
+ id: "custom",
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+const monthday = new Temporal.PlainMonthDay(5, 2, calendar);
+
+TemporalHelpers.checkStringOptionWrongType("calendarName", "auto",
+ (calendarName) => monthday.toString({ calendarName }),
+ (result, descr) => assert.sameValue(result, "1972-05-02[u-ca=custom]", descr),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/length.js
new file mode 100644
index 0000000000..7da082f7fe
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toString, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/name.js
new file mode 100644
index 0000000000..6d6088bd86
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toString, "name", {
+ value: "toString",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/not-a-constructor.js
new file mode 100644
index 0000000000..42bf0e3785
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: >
+ Temporal.PlainMonthDay.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.PlainMonthDay.prototype.toString();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.toString), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.toString)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-object.js
new file mode 100644
index 0000000000..7a57ecb00d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/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.plainmonthday.prototype.tostring
+description: Empty or a function object may be used as options
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+const result1 = instance.toString({});
+assert.sameValue(
+ result1, "05-02",
+ "options may be an empty plain object"
+);
+
+const result2 = instance.toString(() => {});
+assert.sameValue(
+ result2, "05-02",
+ "options may be a function object"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js
new file mode 100644
index 0000000000..c7faf80e88
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-undefined.js
@@ -0,0 +1,51 @@
+// |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.plainmonthday.prototype.tostring
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+---*/
+
+const calendarMethods = {
+ dateAdd() {},
+ dateFromFields() {},
+ dateUntil() {},
+ day() {},
+ dayOfWeek() {},
+ dayOfYear() {},
+ daysInMonth() {},
+ daysInWeek() {},
+ daysInYear() {},
+ fields() {},
+ inLeapYear() {},
+ mergeFields() {},
+ month() {},
+ monthCode() {},
+ monthDayFromFields() {},
+ monthsInYear() {},
+ weekOfYear() {},
+ year() {},
+ yearMonthFromFields() {},
+ yearOfWeek() {},
+};
+
+const tests = [
+ [[], "05-02"],
+ [[{ id: "custom", ...calendarMethods }], "1972-05-02[u-ca=custom]"],
+ [[{ id: "iso8601", ...calendarMethods }], "05-02"],
+ [[{ id: "ISO8601", ...calendarMethods }], "1972-05-02[u-ca=ISO8601]"],
+ [[{ id: "\u0131so8601", ...calendarMethods }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i
+];
+
+for (const [args, expected] of tests) {
+ const monthday = new Temporal.PlainMonthDay(5, 2, ...args);
+ const explicit = monthday.toString(undefined);
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ const implicit = monthday.toString();
+ assert.sameValue(implicit, expected, "default calendarName option is auto");
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js
new file mode 100644
index 0000000000..68b4fb3b51
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/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.plainmonthday.prototype.tostring
+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.PlainMonthDay(5, 2);
+for (const value of badOptions) {
+ assert.throws(TypeError, () => instance.toString(value),
+ `TypeError on wrong options type ${typeof value}`);
+};
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/order-of-operations.js
new file mode 100644
index 0000000000..c56b064c02
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/order-of-operations.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.plainmonthday.prototype.tostring
+description: Properties on an object passed to toString() are accessed in the correct order
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get options.calendarName",
+ "get options.calendarName.toString",
+ "call options.calendarName.toString",
+ "get this.calendar.id",
+];
+const actual = [];
+
+const calendar = TemporalHelpers.calendarObserver(actual, "this.calendar");
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+// clear observable operations that occurred during the constructor call
+actual.splice(0);
+
+const options = TemporalHelpers.propertyBagObserver(actual, {
+ calendarName: "auto",
+}, "options");
+
+instance.toString(options);
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/prop-desc.js
new file mode 100644
index 0000000000..a7bb3e8bc6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype.tostring
+description: The "toString" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.toString,
+ "function",
+ "`typeof PlainMonthDay.prototype.toString` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "toString", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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/PlainMonthDay/prototype/toString/year-format.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js
new file mode 100644
index 0000000000..94db829612
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js
@@ -0,0 +1,58 @@
+// |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.plainmonthday.prototype.tostring
+description: Verify that the year is appropriately formatted as 4 or 6 digits
+features: [Temporal]
+---*/
+
+// For PlainMonthDay, the ISO reference year is only present in the string if
+// the calendar is not ISO 8601
+class NotISO extends Temporal.Calendar {
+ constructor() { super("iso8601"); }
+ get id() { return "not-iso"; }
+}
+const calendar = new NotISO();
+
+let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000);
+assert.sameValue(instance.toString(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000);
+assert.sameValue(instance.toString(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999);
+assert.sameValue(instance.toString(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000);
+assert.sameValue(instance.toString(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(10, 9, calendar, -999);
+assert.sameValue(instance.toString(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 7, calendar, -1);
+assert.sameValue(instance.toString(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(6, 5, calendar, 0);
+assert.sameValue(instance.toString(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(4, 3, calendar, 1);
+assert.sameValue(instance.toString(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(2, 10, calendar, 999);
+assert.sameValue(instance.toString(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000);
+assert.sameValue(instance.toString(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999);
+assert.sameValue(instance.toString(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit");
+
+instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000);
+assert.sameValue(instance.toString(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit");
+
+instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000);
+assert.sameValue(instance.toString(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/prop-desc.js
new file mode 100644
index 0000000000..db4be07058
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/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.plainmonthday.prototype-@@tostringtag
+description: The @@toStringTag property of Temporal.PlainMonthDay
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.PlainMonthDay.prototype, Symbol.toStringTag, {
+ value: "Temporal.PlainMonthDay",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/toStringTag/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.js
new file mode 100644
index 0000000000..0c8ae46a4c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/basic.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.plainmonthday.prototype.valueof
+description: Basic tests for valueOf().
+features: [Temporal]
+---*/
+
+const plainMonthDay = Temporal.PlainMonthDay.from("1963-02-13");
+const plainMonthDay2 = Temporal.PlainMonthDay.from("1963-02-13");
+
+assert.throws(TypeError, () => plainMonthDay.valueOf(), "valueOf");
+assert.throws(TypeError, () => plainMonthDay < plainMonthDay, "<");
+assert.throws(TypeError, () => plainMonthDay <= plainMonthDay, "<=");
+assert.throws(TypeError, () => plainMonthDay > plainMonthDay, ">");
+assert.throws(TypeError, () => plainMonthDay >= plainMonthDay, ">=");
+assert.sameValue(plainMonthDay === plainMonthDay, true, "===");
+assert.sameValue(plainMonthDay === plainMonthDay2, false, "===");
+assert.sameValue(plainMonthDay !== plainMonthDay, false, "!==");
+assert.sameValue(plainMonthDay !== plainMonthDay2, true, "!==");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/branding.js
new file mode 100644
index 0000000000..473c2c8055
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const valueOf = Temporal.PlainMonthDay.prototype.valueOf;
+
+assert.sameValue(typeof valueOf, "function");
+
+assert.throws(TypeError, () => valueOf.call(undefined), "undefined");
+assert.throws(TypeError, () => valueOf.call(null), "null");
+assert.throws(TypeError, () => valueOf.call(true), "true");
+assert.throws(TypeError, () => valueOf.call(""), "empty string");
+assert.throws(TypeError, () => valueOf.call(Symbol()), "symbol");
+assert.throws(TypeError, () => valueOf.call(1), "1");
+assert.throws(TypeError, () => valueOf.call({}), "plain object");
+assert.throws(TypeError, () => valueOf.call(Temporal.PlainMonthDay), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => valueOf.call(Temporal.PlainMonthDay.prototype), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/builtin.js
new file mode 100644
index 0000000000..cc6856df64
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.valueOf
+ 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.PlainMonthDay.prototype.valueOf),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.valueOf),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.valueOf),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.valueOf.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/length.js
new file mode 100644
index 0000000000..755c56bacd
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: Temporal.PlainMonthDay.prototype.valueOf.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.PlainMonthDay.prototype.valueOf, "length", {
+ value: 0,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/name.js
new file mode 100644
index 0000000000..49c1920de7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: Temporal.PlainMonthDay.prototype.valueOf.name is "valueOf".
+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.PlainMonthDay.prototype.valueOf, "name", {
+ value: "valueOf",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/not-a-constructor.js
new file mode 100644
index 0000000000..61ab175d2a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: >
+ Temporal.PlainMonthDay.prototype.valueOf 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.PlainMonthDay.prototype.valueOf();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.valueOf), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.valueOf)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/prop-desc.js
new file mode 100644
index 0000000000..13deb2da8d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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.plainmonthday.prototype.valueof
+description: The "valueOf" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.valueOf,
+ "function",
+ "`typeof PlainMonthDay.prototype.valueOf` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "valueOf", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/valueOf/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/PlainMonthDay/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js
new file mode 100644
index 0000000000..27f4069fc4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/basic.js
@@ -0,0 +1,44 @@
+// |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.plainmonthday.prototype.with
+description: Basic tests for with().
+includes: [compareArray.js, temporalHelpers.js]
+features: [Symbol, Temporal]
+---*/
+
+const md = Temporal.PlainMonthDay.from("01-15");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ day: 22 }),
+ "M01", 22, "with({day})");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ month: 12 }),
+ "M12", 15, "with({month})");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ monthCode: "M12" }),
+ "M12", 15, "with({monthCode})");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ month: 12, monthCode: "M12" }),
+ "M12", 15, "with({month, monthCode}) agree");
+
+assert.throws(RangeError, () => md.with({ month: 12, monthCode: "M11" }), "with({month, monthCode}) disagree");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ year: 2000, month: 12 }),
+ "M12", 15, "with({year, month})");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ year: 2000 }),
+ "M01", 15, "with({year})");
+
+assert.throws(TypeError, () => md.with({ day: 1, calendar: "iso8601" }), "with({calendar})");
+
+assert.throws(TypeError, () => md.with({ day: 1, timeZone: "UTC" }), "with({timeZone})");
+
+assert.throws(TypeError, () => md.with({}), "with({})");
+assert.throws(TypeError, () => md.with({ months: 12 }), "with({months})");
+
+TemporalHelpers.assertPlainMonthDay(md.with({ monthCode: "M12", days: 1 }),
+ "M12", 15, "with({monthCode, days})");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/branding.js
new file mode 100644
index 0000000000..1df04554e4
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/branding.js
@@ -0,0 +1,27 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: Throw a TypeError if the receiver is invalid
+features: [Symbol, Temporal]
+---*/
+
+const with_ = Temporal.PlainMonthDay.prototype.with;
+
+assert.sameValue(typeof with_, "function");
+
+const args = [{ year: 2022, month: 12 }];
+
+assert.throws(TypeError, () => with_.apply(undefined, args), "undefined");
+assert.throws(TypeError, () => with_.apply(null, args), "null");
+assert.throws(TypeError, () => with_.apply(true, args), "true");
+assert.throws(TypeError, () => with_.apply("", args), "empty string");
+assert.throws(TypeError, () => with_.apply(Symbol(), args), "symbol");
+assert.throws(TypeError, () => with_.apply(1, args), "1");
+assert.throws(TypeError, () => with_.apply({}, args), "plain object");
+assert.throws(TypeError, () => with_.apply(Temporal.PlainMonthDay, args), "Temporal.PlainMonthDay");
+assert.throws(TypeError, () => with_.apply(Temporal.PlainMonthDay.prototype, args), "Temporal.PlainMonthDay.prototype");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/browser.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/browser.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-array-iteration.js
new file mode 100644
index 0000000000..10936aca0b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-array-iteration.js
@@ -0,0 +1,23 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable array iteration when getting the calendar fields.
+features: [Temporal]
+---*/
+
+const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator];
+Array.prototype[Symbol.iterator] = function arrayIterator() {
+ throw new Test262Error("Array should not be iterated");
+}
+
+const instance = new Temporal.PlainMonthDay(5, 1, "iso8601");
+instance.with({ monthCode: "M04" });
+
+Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-observable-calls.js
new file mode 100644
index 0000000000..5b4469a1d8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin-calendar-no-observable-calls.js
@@ -0,0 +1,46 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Calling the method on an instance constructed with a builtin calendar causes
+ no observable lookups or calls to calendar methods.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const fieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "fields");
+Object.defineProperty(Temporal.Calendar.prototype, "fields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("fields should not be looked up");
+ },
+});
+const mergeFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "mergeFields");
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("mergeFields should not be looked up");
+ },
+});
+const monthDayFromFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "monthDayFromFields");
+Object.defineProperty(Temporal.Calendar.prototype, "monthDayFromFields", {
+ configurable: true,
+ enumerable: false,
+ get() {
+ TemporalHelpers.assertUnreachable("monthDayFromFields should not be looked up");
+ },
+});
+
+const instance = new Temporal.PlainMonthDay(5, 2, "iso8601", 1972);
+instance.with({ monthCode: "M06" });
+
+Object.defineProperty(Temporal.Calendar.prototype, "fields", fieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "mergeFields", mergeFieldsOriginal);
+Object.defineProperty(Temporal.Calendar.prototype, "monthDayFromFields", monthDayFromFieldsOriginal);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js
new file mode 100644
index 0000000000..a94e0fd066
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/builtin.js
@@ -0,0 +1,36 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Tests that Temporal.PlainMonthDay.prototype.with
+ meets the requirements for built-in objects defined by the
+ introduction of chapter 17 of the ECMAScript Language Specification.
+info: |
+ Built-in functions that are not constructors do not have a "prototype" property unless
+ otherwise specified in the description of a particular function.
+
+ Unless specified otherwise, a built-in object that is callable as a function is a built-in
+ function object with the characteristics described in 10.3. Unless specified otherwise, the
+ [[Extensible]] internal slot of a built-in object initially has the value true.
+
+ Unless otherwise specified every built-in function and every built-in constructor has the
+ Function prototype object [...] as the value of its [[Prototype]] internal slot.
+features: [Temporal]
+---*/
+
+assert.sameValue(Object.isExtensible(Temporal.PlainMonthDay.prototype.with),
+ true, "Built-in objects must be extensible.");
+
+assert.sameValue(Object.prototype.toString.call(Temporal.PlainMonthDay.prototype.with),
+ "[object Function]", "Object.prototype.toString");
+
+assert.sameValue(Object.getPrototypeOf(Temporal.PlainMonthDay.prototype.with),
+ Function.prototype, "prototype");
+
+assert.sameValue(Temporal.PlainMonthDay.prototype.with.hasOwnProperty("prototype"),
+ false, "prototype property");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.js
new file mode 100644
index 0000000000..5f98ed2e34
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-arguments.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.plainmonthday.prototype.with
+description: Correct options value is passed to calendar method
+info: |
+ MonthDayFromFields ( calendar, fields [ , options ] )
+
+ 5. Let monthDay be ? Invoke(calendar, "monthDayFromFields", « fields, options »).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const options = {
+ extra: "property",
+};
+class CustomCalendar extends Temporal.Calendar {
+ constructor() {
+ super("iso8601");
+ }
+ monthDayFromFields(...args) {
+ assert.sameValue(args.length, 2, "args.length");
+ assert.sameValue(typeof args[0], "object", "args[0]");
+ assert.notSameValue(args[1], options, "args[1] is a copy of options");
+ assert.sameValue(args[1].extra, "property", "All properties are copied");
+ assert.sameValue(Object.getPrototypeOf(args[1]), null, "Copy has null prototype");
+ return super.monthDayFromFields(...args);
+ }
+}
+const plainMonthDay = new Temporal.PlainMonthDay(7, 2, new CustomCalendar());
+const result = plainMonthDay.with({ monthCode: "M05" }, options);
+TemporalHelpers.assertPlainMonthDay(result, "M05", 2);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js
new file mode 100644
index 0000000000..6d944a6cf7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fields-iterable.js
@@ -0,0 +1,32 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: Verify the result of calendar.fields() is treated correctly.
+info: |
+ sec-temporal.plainmonthday.prototype.with step 9:
+ 9. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
+ sec-temporal-calendarfields step 4:
+ 4. Let _result_ be ? IterableToList(_fieldsArray_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "day",
+ "month",
+ "monthCode",
+ "year",
+];
+
+const calendar = TemporalHelpers.calendarFieldsIterable();
+const monthday = new Temporal.PlainMonthDay(5, 2, calendar);
+monthday.with({ day: 6 });
+
+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/PlainMonthDay/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..f7f5b57d89
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-fromfields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Calendar.monthDayFromFields method is called with a null-prototype fields object
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+instance.with({ day: 24 });
+assert.sameValue(calendar.monthDayFromFieldsCallCount, 1, "monthDayFromFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js
new file mode 100644
index 0000000000..c181271486
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-merge-fields-returns-primitive.js
@@ -0,0 +1,21 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ with() should throw a TypeError if mergeFields() returns a primitive,
+ without passing the value on to any other calendar methods
+includes: [compareArray.js, temporalHelpers.js]
+features: [BigInt, Symbol, Temporal]
+---*/
+
+[undefined, null, true, 3.14159, "bad value", Symbol("no"), 7n].forEach((primitive) => {
+ const calendar = TemporalHelpers.calendarMergeFieldsReturnsPrimitive(primitive);
+ const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+ assert.throws(TypeError, () => instance.with({ year: 2005 }), "bad return from mergeFields() throws");
+ assert.sameValue(calendar.monthDayFromFieldsCallCount, 0, "monthDayFromFields() never called");
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
new file mode 100644
index 0000000000..a91186566a
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/calendar-mergefields-called-with-null-prototype-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Calendar.mergeFields method is called with null-prototype fields objects
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarCheckMergeFieldsPrototypePollution();
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+instance.with({ day: 24 });
+assert.sameValue(calendar.mergeFieldsCallCount, 1, "mergeFields should have been called on the calendar");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/constructor-in-calendar-fields.js
new file mode 100644
index 0000000000..6d56671dde
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/constructor-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']);
+const md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+assert.throws(RangeError, () => md.with({day: 15}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.js
new file mode 100644
index 0000000000..36b0941bb1
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copies-merge-fields-object.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.plainmonthday.prototype.with
+description: The object returned from mergeFields() is copied before being passed to monthDayFromFields().
+info: |
+ sec-temporal.plainmonthday.prototype.with steps 13–15:
+ 13. Set _fields_ to ? CalendarMergeFields(_calendar_, _fields_, _partialMonthDay_).
+ 14. Set _fields_ to ? PrepareTemporalFields(_fields_, _fieldNames_, «»).
+ 15. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ "get day",
+ "get day.valueOf",
+ "call day.valueOf",
+ "get month", // PlainMonthDay.month property does not exist, no valueOf
+ "get monthCode",
+ "get monthCode.toString",
+ "call monthCode.toString",
+ "get year", // undefined, no valueOf
+];
+
+const calendar = TemporalHelpers.calendarMergeFieldsGetters();
+const monthday = new Temporal.PlainMonthDay(3, 31, calendar);
+monthday.with({ day: 1 });
+
+assert.compareArray(calendar.mergeFieldsReturnOperations, expected, "getters called on mergeFields return");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.js
new file mode 100644
index 0000000000..8458c5bb3b
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/copy-properties-not-undefined.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.plainmonthday.prototype.with
+description: PreparePartialTemporalFields copies only defined properties of source object
+info: |
+ 4. For each value _property_ of _fieldNames_, do
+ a. Let _value_ be ? Get(_fields_, _property_).
+ b. If _value_ is not *undefined*, then
+ ...
+ iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const plainMonthDay = new Temporal.PlainMonthDay(10, 31);
+
+TemporalHelpers.assertPlainMonthDay(plainMonthDay.with({ day: 1, monthCode: undefined }),
+ "M10", 1,
+ "only the properties that are present and defined in the plain object are copied"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/duplicate-calendar-fields.js
new file mode 100644
index 0000000000..566b013308
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/duplicate-calendar-fields.js
@@ -0,0 +1,18 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+for (const extra_fields of [['foo', 'foo'], ['monthCode'], ['day'], ['month'], ['year']]) {
+ const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
+ const md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+ assert.throws(RangeError, () => md.with({day: 15}));
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.js
new file mode 100644
index 0000000000..bc7b3da926
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/infinity-throws-rangeerror.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.
+
+/*---
+description: Throws if any value in the property bag is Infinity or -Infinity
+esid: sec-temporal.plainmonthday.prototype.with
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+[Infinity, -Infinity].forEach((inf) => {
+ ["constrain", "reject"].forEach((overflow) => {
+ assert.throws(RangeError, () => instance.with({ day: inf }, { overflow }), `day property cannot be ${inf} (overflow ${overflow}`);
+
+ const calls = [];
+ const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "day");
+ assert.throws(RangeError, () => instance.with({ day: obj }, { overflow }));
+ assert.compareArray(calls, ["get day.valueOf", "call day.valueOf"], "it fails after fetching the primitive value");
+ });
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/length.js
new file mode 100644
index 0000000000..dd129874fa
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/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.plainmonthday.prototype.with
+description: Temporal.PlainMonthDay.prototype.with.length is 1
+info: |
+ Every built-in function object, including constructors, has a "length" property whose value is
+ an integer. Unless otherwise specified, this value is equal to the largest number of named
+ arguments shown in the subclause headings for the function description. Optional parameters
+ (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form
+ «...name») are not included in the default argument count.
+
+ Unless otherwise specified, the "length" property of a built-in function object has the
+ attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.PlainMonthDay.prototype.with, "length", {
+ value: 1,
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js
new file mode 100644
index 0000000000..c1a4873a71
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/name.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: Temporal.PlainMonthDay.prototype.with.name is "with".
+info: |
+ Every built-in function object, including constructors, that is not identified as an anonymous
+ function has a "name" property whose value is a String. Unless otherwise specified, this value
+ is the name that is given to the function in this specification.
+
+ Unless otherwise specified, the "name" property of a built-in function object, if it exists,
+ has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+verifyProperty(Temporal.PlainMonthDay.prototype.with, "name", {
+ value: "with",
+ writable: false,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js
new file mode 100644
index 0000000000..d47adfe1c3
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/not-a-constructor.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: >
+ Temporal.PlainMonthDay.prototype.with does not implement [[Construct]], is not new-able
+info: |
+ Built-in function objects that are not identified as constructors do not implement the
+ [[Construct]] internal method unless otherwise specified in the description of a particular
+ function.
+includes: [isConstructor.js]
+features: [Reflect.construct, Temporal]
+---*/
+
+assert.throws(TypeError, () => {
+ new Temporal.PlainMonthDay.prototype.with();
+}, "Calling as constructor");
+
+assert.sameValue(isConstructor(Temporal.PlainMonthDay.prototype.with), false,
+ "isConstructor(Temporal.PlainMonthDay.prototype.with)");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js
new file mode 100644
index 0000000000..d51439c247
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-invalid.js
@@ -0,0 +1,16 @@
+// |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.plainmonthday.prototype.with
+description: TypeError thrown when options argument is a primitive
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(2, 2);
+[null, true, "hello", Symbol("foo"), 1, 1n].forEach((badOptions) =>
+ assert.throws(TypeError, () => instance.with({ day: 17 }, badOptions))
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-object.js
new file mode 100644
index 0000000000..29c79e3104
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-object.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.plainmonthday.prototype.with
+description: Empty or a function object may be used as options
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+
+const result1 = instance.with({ day: 5 }, {});
+TemporalHelpers.assertPlainMonthDay(
+ result1, "M05", 5,
+ "options may be an empty plain object"
+);
+
+const result2 = instance.with({ day: 5 }, () => {});
+TemporalHelpers.assertPlainMonthDay(
+ result2, "M05", 5,
+ "options may be a function object"
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js
new file mode 100644
index 0000000000..24134ef2ba
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-undefined.js
@@ -0,0 +1,20 @@
+// |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.plainmonthday.prototype.with
+description: Verify that undefined options are handled correctly.
+features: [Temporal]
+---*/
+
+const monthday = new Temporal.PlainMonthDay(2, 2);
+const fields = { day: 100 };
+
+const explicit = monthday.with(fields, undefined);
+assert.sameValue(explicit.day, 29, "default overflow is constrain");
+
+const implicit = monthday.with(fields);
+assert.sameValue(implicit.day, 29, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js
new file mode 100644
index 0000000000..c4026fa84c
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js
@@ -0,0 +1,26 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2022 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: TypeError thrown when options argument is a primitive
+features: [BigInt, Symbol, Temporal]
+---*/
+
+const badOptions = [
+ null,
+ true,
+ "some string",
+ Symbol(),
+ 1,
+ 2n,
+];
+
+const instance = new Temporal.PlainMonthDay(5, 2);
+for (const value of badOptions) {
+ assert.throws(TypeError, () => instance.with({ day: 5 }, value),
+ `TypeError on wrong options type ${typeof value}`);
+};
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js
new file mode 100644
index 0000000000..2311bf7a6f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/order-of-operations.js
@@ -0,0 +1,76 @@
+// |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.plainmonthday.prototype.with
+description: Properties on an object passed to with() are accessed in the correct order
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const expected = [
+ // RejectObjectWithCalendarOrTimeZone
+ "get fields.calendar",
+ "get fields.timeZone",
+ // CopyDataProperties
+ "ownKeys options",
+ "getOwnPropertyDescriptor options.overflow",
+ "get options.overflow",
+ "getOwnPropertyDescriptor options.extra",
+ "get options.extra",
+ // lookup
+ "get this.calendar.fields",
+ "get this.calendar.mergeFields",
+ "get this.calendar.monthDayFromFields",
+ // CalendarFields
+ "call this.calendar.fields",
+ // PrepareTemporalFields on receiver
+ "get this.calendar.day",
+ "call this.calendar.day",
+ "get this.calendar.monthCode",
+ "call this.calendar.monthCode",
+ // PrepareTemporalFields on argument
+ "get fields.day",
+ "get fields.day.valueOf",
+ "call fields.day.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.year",
+ "get fields.year.valueOf",
+ "call fields.year.valueOf",
+ // CalendarMergeFields
+ "call this.calendar.mergeFields",
+ // CalendarMonthDayFromFields
+ "call this.calendar.monthDayFromFields",
+ // inside Calendar.p.monthDayFromFields
+ "get options.overflow.toString",
+ "call options.overflow.toString",
+];
+const actual = [];
+
+const calendar = TemporalHelpers.calendarObserver(actual, "this.calendar");
+const instance = new Temporal.PlainMonthDay(5, 2, calendar);
+// clear observable operations that occurred during the constructor call
+actual.splice(0);
+
+const fields = TemporalHelpers.propertyBagObserver(actual, {
+ year: 1.7,
+ month: 1.7,
+ monthCode: "M01",
+ day: 1.7,
+}, "fields");
+
+const options = TemporalHelpers.propertyBagObserver(actual, {
+ overflow: "constrain",
+ extra: "property",
+}, "options");
+
+instance.with(fields, options);
+assert.compareArray(actual, expected, "order of operations");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..bc845f5bb7
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,31 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: RangeError thrown when overflow option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-isomonthdayfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.prototype.with step 16:
+ 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+features: [Temporal]
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+
+const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"];
+for (const overflow of badOverflows) {
+ assert.throws(
+ RangeError,
+ () => monthday.with({ day: 8 }, { overflow }),
+ `invalid overflow ("${overflow}")`
+ );
+}
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..0f93fe809d
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-undefined.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.plainmonthday.prototype.with
+description: Fallback value for overflow option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-isomonthdayfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.prototype.with step 16:
+ 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+const explicit = monthday.with({ day: 33 }, { overflow: undefined });
+TemporalHelpers.assertPlainMonthDay(explicit, "M05", 31, "default overflow is constrain");
+const implicit = monthday.with({ day: 33 }, {});
+TemporalHelpers.assertPlainMonthDay(implicit, "M05", 31, "default overflow is constrain");
+const lambda = monthday.with({ day: 33 }, () => {});
+TemporalHelpers.assertPlainMonthDay(lambda, "M05", 31, "default overflow is constrain");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..f6d4a649e8
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-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.plainmonthday.prototype.with
+description: Type conversions for overflow option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-isomonthdayfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainmonthday.prototype.with step 16:
+ 16. Return ? MonthDayFromFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => monthday.with({ day: 8 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 8, descr),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js
new file mode 100644
index 0000000000..32126c982f
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/prop-desc.js
@@ -0,0 +1,24 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: The "with" property of Temporal.PlainMonthDay.prototype
+includes: [propertyHelper.js]
+features: [Temporal]
+---*/
+
+assert.sameValue(
+ typeof Temporal.PlainMonthDay.prototype.with,
+ "function",
+ "`typeof PlainMonthDay.prototype.with` is `function`"
+);
+
+verifyProperty(Temporal.PlainMonthDay.prototype, "with", {
+ writable: true,
+ enumerable: false,
+ configurable: true,
+});
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/proto-in-calendar-fields.js
new file mode 100644
index 0000000000..805706edb6
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/proto-in-calendar-fields.js
@@ -0,0 +1,16 @@
+// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally
+// Copyright (C) 2023 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-temporal.plainmonthday.prototype.with
+description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']);
+const md = new Temporal.PlainMonthDay(5, 1, calendar);
+
+assert.throws(RangeError, () => md.with({day: 15}));
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js
new file mode 100644
index 0000000000..eda1477282
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/shell.js
@@ -0,0 +1,24 @@
+// GENERATED, DO NOT EDIT
+// file: isConstructor.js
+// Copyright (C) 2017 André Bargull. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: |
+ Test if a given function is a constructor function.
+defines: [isConstructor]
+features: [Reflect.construct]
+---*/
+
+function isConstructor(f) {
+ if (typeof f !== "function") {
+ throw new Test262Error("isConstructor invoked with a non-function value");
+ }
+
+ try {
+ Reflect.construct(function(){}, [], f);
+ } catch (e) {
+ return false;
+ }
+ return true;
+}
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js
new file mode 100644
index 0000000000..a232d529d0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/prototype/with/subclassing-ignored.js
@@ -0,0 +1,20 @@
+// |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.plainmonthday.prototype.with
+description: Objects of a subclass are never created as return values for with()
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+TemporalHelpers.checkSubclassingIgnored(
+ Temporal.PlainMonthDay,
+ [5, 2],
+ "with",
+ [{ day: 20 }],
+ (result) => TemporalHelpers.assertPlainMonthDay(result, "M05", 20),
+);
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-out-of-range.js
new file mode 100644
index 0000000000..bf6049a1cb
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-out-of-range.js
@@ -0,0 +1,16 @@
+// |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.plainmonthday
+description: referenceISOYear argument, if given, can cause RangeError
+features: [Temporal]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(9, 14, calendar, 275760), "after the maximum ISO date");
+assert.throws(RangeError, () => new Temporal.PlainMonthDay(4, 18, calendar, -271821), "before the minimum ISO date")
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js
new file mode 100644
index 0000000000..572d76a1e2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/refisoyear-undefined.js
@@ -0,0 +1,20 @@
+// |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.plainmonthday
+description: referenceISOYear argument defaults to 1972 if not given
+features: [Temporal]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+const args = [5, 2, calendar];
+
+const dateExplicit = new Temporal.PlainMonthDay(...args, undefined);
+assert.sameValue(dateExplicit.getISOFields().isoYear, 1972, "default referenceISOYear is 1972");
+
+const dateImplicit = new Temporal.PlainMonthDay(...args);
+assert.sameValue(dateImplicit.getISOFields().isoYear, 1972, "default referenceISOYear is 1972");
+
+reportCompare(0, 0);
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/shell.js
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/subclass.js b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/subclass.js
new file mode 100644
index 0000000000..8040302fb0
--- /dev/null
+++ b/js/src/tests/test262/built-ins/Temporal/PlainMonthDay/subclass.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.plainmonthday
+description: Test for Temporal.PlainMonthDay subclassing.
+includes: [temporalHelpers.js]
+features: [Temporal]
+---*/
+
+class CustomPlainMonthDay extends Temporal.PlainMonthDay {
+}
+
+const instance = new CustomPlainMonthDay(5, 2);
+TemporalHelpers.assertPlainMonthDay(instance, "M05", 2);
+assert.sameValue(Object.getPrototypeOf(instance), CustomPlainMonthDay.prototype, "Instance of CustomPlainMonthDay");
+assert(instance instanceof CustomPlainMonthDay, "Instance of CustomPlainMonthDay");
+assert(instance instanceof Temporal.PlainMonthDay, "Instance of Temporal.PlainMonthDay");
+
+reportCompare(0, 0);