From 1f92033d1eb8d6b8f82781304eb6aa1ae89d3323 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Wed, 28 Apr 2021 17:48:46 -0700
Subject: [PATCH] Editorial: Consolidate GetOption usage
Under the assumption that it's not a priority to move GetNumberOption
directly from ECMA-402 into ECMA-262, reorganize the GetOption operations:
- Change the _type_ string argument to GetOption, into a List of valid
types, the last one of which will be coerced to if the value is none of
them (and also not undefined).
- In the Number case, call ToNumber on the value and throw if it is NaN.
- Inline GetNumberOption as it's only called once.
- Call GetOption in GetStringOrNumberOption.
- Don't delete GetOption, GetNumberOption, and DefaultNumberOption from
402, as they won't be replaced by anything in 262 at present.
Includes a fix to make the polyfill spec-compliant, and test262 tests
covering usages of GetOption (there are quite a lot of them.)
Closes: #1411
---
polyfill/lib/ecmascript.mjs | 8 +-
.../dateAdd/overflow-invalid-string.js | 19 +++
.../prototype/dateAdd/overflow-undefined.js | 24 ++++
.../prototype/dateAdd/overflow-wrong-type.js | 23 ++++
.../dateFromFields/overflow-invalid-string.js | 19 +++
.../dateFromFields/overflow-undefined.js | 24 ++++
.../dateFromFields/overflow-wrong-type.js | 23 ++++
.../overflow-invalid-string.js | 19 +++
.../monthDayFromFields/overflow-undefined.js | 24 ++++
.../monthDayFromFields/overflow-wrong-type.js | 23 ++++
.../overflow-invalid-string.js | 19 +++
.../yearMonthFromFields/overflow-undefined.js | 24 ++++
.../overflow-wrong-type.js | 23 ++++
.../round/largestunit-invalid-string.js | 10 ++
.../prototype/round/largestunit-undefined.js | 20 ++++
.../prototype/round/largestunit-wrong-type.js | 14 +++
.../prototype/round/roundingincrement-nan.js | 17 +++
.../round/roundingincrement-undefined.js | 23 ++++
.../round/roundingincrement-wrong-type.js | 23 ++++
.../round/roundingmode-invalid-string.js | 10 ++
.../prototype/round/roundingmode-undefined.js | 25 ++++
.../round/roundingmode-wrong-type.js | 14 +++
.../round/smallestunit-invalid-string.js | 10 ++
.../prototype/round/smallestunit-undefined.js | 14 +++
.../round/smallestunit-wrong-type.js | 14 +++
.../fractionalseconddigits-invalid-string.js | 18 +++
.../toString/fractionalseconddigits-nan.js | 19 +++
.../fractionalseconddigits-non-integer.js | 19 +++
.../fractionalseconddigits-out-of-range.js | 19 +++
.../fractionalseconddigits-undefined.js | 24 ++++
.../fractionalseconddigits-wrong-type.js | 24 ++++
.../toString/roundingmode-invalid-string.js | 10 ++
.../toString/roundingmode-undefined.js | 25 ++++
.../toString/roundingmode-wrong-type.js | 14 +++
.../toString/smallestunit-invalid-string.js | 10 ++
.../toString/smallestunit-undefined.js | 20 ++++
.../toString/smallestunit-wrong-type.js | 14 +++
.../prototype/total/unit-invalid-string.js | 17 +++
.../prototype/total/unit-wrong-type.js | 21 ++++
.../prototype/round/roundingincrement-nan.js | 17 +++
.../round/roundingincrement-undefined.js | 22 ++++
.../round/roundingincrement-wrong-type.js | 23 ++++
.../round/roundingmode-invalid-string.js | 10 ++
.../prototype/round/roundingmode-undefined.js | 25 ++++
.../round/roundingmode-wrong-type.js | 14 +++
.../round/smallestunit-invalid-string.js | 10 ++
.../round/smallestunit-wrong-type.js | 14 +++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 24 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 26 +++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../fractionalseconddigits-invalid-string.js | 18 +++
.../toString/fractionalseconddigits-nan.js | 20 ++++
.../fractionalseconddigits-non-integer.js | 19 +++
.../fractionalseconddigits-out-of-range.js | 19 +++
.../fractionalseconddigits-undefined.js | 24 ++++
.../fractionalseconddigits-wrong-type.js | 24 ++++
.../toString/roundingmode-invalid-string.js | 10 ++
.../toString/roundingmode-undefined.js | 25 ++++
.../toString/roundingmode-wrong-type.js | 14 +++
.../toString/smallestunit-invalid-string.js | 10 ++
.../toString/smallestunit-undefined.js | 20 ++++
.../toString/smallestunit-wrong-type.js | 14 +++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 24 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 26 +++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../from/overflow-invalid-string.js | 31 +++++
.../constructor/from/overflow-undefined.js | 40 +++++++
.../constructor/from/overflow-wrong-type.js | 33 ++++++
.../prototype/add/overflow-invalid-string.js | 20 ++++
.../prototype/add/overflow-undefined.js | 25 ++++
.../prototype/add/overflow-wrong-type.js | 24 ++++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 23 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 22 ++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../subtract/overflow-invalid-string.js | 20 ++++
.../prototype/subtract/overflow-undefined.js | 25 ++++
.../prototype/subtract/overflow-wrong-type.js | 24 ++++
.../toString/calendarname-invalid-string.js | 17 +++
.../toString/calendarname-undefined.js | 31 +++++
.../toString/calendarname-wrong-type.js | 25 ++++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 23 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 22 ++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../prototype/with/overflow-invalid-string.js | 19 +++
.../prototype/with/overflow-undefined.js | 23 ++++
.../prototype/with/overflow-wrong-type.js | 23 ++++
.../from/overflow-invalid-string.js | 35 ++++++
.../constructor/from/overflow-undefined.js | 44 +++++++
.../constructor/from/overflow-wrong-type.js | 62 ++++++++++
.../prototype/add/overflow-invalid-string.js | 22 ++++
.../prototype/add/overflow-undefined.js | 27 +++++
.../prototype/add/overflow-wrong-type.js | 26 +++++
.../prototype/round/roundingincrement-nan.js | 19 +++
.../round/roundingincrement-undefined.js | 25 ++++
.../round/roundingincrement-wrong-type.js | 25 ++++
.../round/roundingmode-invalid-string.js | 10 ++
.../prototype/round/roundingmode-undefined.js | 25 ++++
.../round/roundingmode-wrong-type.js | 14 +++
.../round/smallestunit-invalid-string.js | 10 ++
.../round/smallestunit-wrong-type.js | 14 +++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 24 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 26 +++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../subtract/overflow-invalid-string.js | 22 ++++
.../prototype/subtract/overflow-undefined.js | 27 +++++
.../prototype/subtract/overflow-wrong-type.js | 26 +++++
.../toString/calendarname-invalid-string.js | 17 +++
.../toString/calendarname-undefined.js | 30 +++++
.../toString/calendarname-wrong-type.js | 25 ++++
.../fractionalseconddigits-invalid-string.js | 18 +++
.../toString/fractionalseconddigits-nan.js | 19 +++
.../fractionalseconddigits-non-integer.js | 19 +++
.../fractionalseconddigits-out-of-range.js | 19 +++
.../fractionalseconddigits-undefined.js | 23 ++++
.../fractionalseconddigits-wrong-type.js | 24 ++++
.../toString/roundingmode-invalid-string.js | 10 ++
.../toString/roundingmode-undefined.js | 25 ++++
.../toString/roundingmode-wrong-type.js | 14 +++
.../toString/smallestunit-invalid-string.js | 10 ++
.../toString/smallestunit-undefined.js | 20 ++++
.../toString/smallestunit-wrong-type.js | 14 +++
.../disambiguation-invalid-string.js | 18 +++
.../disambiguation-undefined.js | 29 +++++
.../disambiguation-wrong-type.js | 22 ++++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 24 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 26 +++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../prototype/with/overflow-invalid-string.js | 20 ++++
.../prototype/with/overflow-undefined.js | 24 ++++
.../prototype/with/overflow-wrong-type.js | 45 ++++++++
.../from/overflow-invalid-string.js | 31 +++++
.../constructor/from/overflow-undefined.js | 40 +++++++
.../constructor/from/overflow-wrong-type.js | 33 ++++++
.../toString/calendarname-invalid-string.js | 17 +++
.../toString/calendarname-undefined.js | 31 +++++
.../toString/calendarname-wrong-type.js | 25 ++++
.../prototype/with/overflow-invalid-string.js | 19 +++
.../prototype/with/overflow-undefined.js | 23 ++++
.../prototype/with/overflow-wrong-type.js | 23 ++++
.../from/overflow-invalid-string.js | 23 ++++
.../constructor/from/overflow-undefined.js | 32 ++++++
.../constructor/from/overflow-wrong-type.js | 25 ++++
.../prototype/round/roundingincrement-nan.js | 17 +++
.../round/roundingincrement-undefined.js | 23 ++++
.../round/roundingincrement-wrong-type.js | 23 ++++
.../round/roundingmode-invalid-string.js | 10 ++
.../prototype/round/roundingmode-undefined.js | 25 ++++
.../round/roundingmode-wrong-type.js | 14 +++
.../round/smallestunit-invalid-string.js | 10 ++
.../round/smallestunit-wrong-type.js | 14 +++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 24 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 26 +++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../fractionalseconddigits-invalid-string.js | 18 +++
.../toString/fractionalseconddigits-nan.js | 19 +++
.../fractionalseconddigits-non-integer.js | 19 +++
.../fractionalseconddigits-out-of-range.js | 19 +++
.../fractionalseconddigits-undefined.js | 24 ++++
.../fractionalseconddigits-wrong-type.js | 24 ++++
.../toString/roundingmode-invalid-string.js | 10 ++
.../toString/roundingmode-undefined.js | 25 ++++
.../toString/roundingmode-wrong-type.js | 14 +++
.../toString/smallestunit-invalid-string.js | 10 ++
.../toString/smallestunit-undefined.js | 20 ++++
.../toString/smallestunit-wrong-type.js | 14 +++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 24 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 26 +++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../prototype/with/overflow-invalid-string.js | 17 +++
.../prototype/with/overflow-undefined.js | 21 ++++
.../prototype/with/overflow-wrong-type.js | 21 ++++
.../from/overflow-invalid-string.js | 31 +++++
.../constructor/from/overflow-undefined.js | 40 +++++++
.../constructor/from/overflow-wrong-type.js | 33 ++++++
.../prototype/add/overflow-invalid-string.js | 22 ++++
.../prototype/add/overflow-undefined.js | 30 +++++
.../prototype/add/overflow-wrong-type.js | 46 ++++++++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 24 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 22 ++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../subtract/overflow-invalid-string.js | 22 ++++
.../prototype/subtract/overflow-undefined.js | 30 +++++
.../prototype/subtract/overflow-wrong-type.js | 46 ++++++++
.../toString/calendarname-invalid-string.js | 17 +++
.../toString/calendarname-undefined.js | 31 +++++
.../toString/calendarname-wrong-type.js | 25 ++++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 24 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 22 ++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../prototype/with/overflow-invalid-string.js | 19 +++
.../prototype/with/overflow-undefined.js | 23 ++++
.../prototype/with/overflow-wrong-type.js | 23 ++++
.../disambiguation-invalid-string.js | 18 +++
.../getInstantFor/disambiguation-undefined.js | 29 +++++
.../disambiguation-wrong-type.js | 22 ++++
.../from/disambiguation-invalid-string.js | 28 +++++
.../from/disambiguation-undefined.js | 34 ++++++
.../from/disambiguation-wrong-type.js | 35 ++++++
.../constructor/from/offset-invalid-string.js | 27 +++++
.../constructor/from/offset-undefined.js | 26 +++++
.../constructor/from/offset-wrong-type.js | 34 ++++++
.../from/overflow-invalid-string.js | 36 ++++++
.../constructor/from/overflow-undefined.js | 45 ++++++++
.../constructor/from/overflow-wrong-type.js | 63 ++++++++++
.../prototype/add/overflow-invalid-string.js | 22 ++++
.../prototype/add/overflow-undefined.js | 26 +++++
.../prototype/add/overflow-wrong-type.js | 26 +++++
.../prototype/round/roundingincrement-nan.js | 19 +++
.../round/roundingincrement-undefined.js | 24 ++++
.../round/roundingincrement-wrong-type.js | 25 ++++
.../round/roundingmode-invalid-string.js | 10 ++
.../prototype/round/roundingmode-undefined.js | 25 ++++
.../round/roundingmode-wrong-type.js | 14 +++
.../round/smallestunit-invalid-string.js | 10 ++
.../round/smallestunit-wrong-type.js | 14 +++
.../since/largestunit-invalid-string.js | 11 ++
.../prototype/since/largestunit-undefined.js | 16 +++
.../prototype/since/largestunit-wrong-type.js | 15 +++
.../prototype/since/roundingincrement-nan.js | 18 +++
.../since/roundingincrement-undefined.js | 24 ++++
.../since/roundingincrement-wrong-type.js | 24 ++++
.../since/roundingmode-invalid-string.js | 11 ++
.../prototype/since/roundingmode-undefined.js | 26 +++++
.../since/roundingmode-wrong-type.js | 15 +++
.../since/smallestunit-invalid-string.js | 11 ++
.../prototype/since/smallestunit-undefined.js | 16 +++
.../since/smallestunit-wrong-type.js | 15 +++
.../subtract/overflow-invalid-string.js | 22 ++++
.../prototype/subtract/overflow-undefined.js | 26 +++++
.../prototype/subtract/overflow-wrong-type.js | 26 +++++
.../toString/calendarname-invalid-string.js | 17 +++
.../toString/calendarname-undefined.js | 31 +++++
.../toString/calendarname-wrong-type.js | 25 ++++
.../fractionalseconddigits-invalid-string.js | 18 +++
.../toString/fractionalseconddigits-nan.js | 19 +++
.../fractionalseconddigits-non-integer.js | 19 +++
.../fractionalseconddigits-out-of-range.js | 19 +++
.../fractionalseconddigits-undefined.js | 23 ++++
.../fractionalseconddigits-wrong-type.js | 24 ++++
.../toString/offset-invalid-string.js | 17 +++
.../prototype/toString/offset-undefined.js | 21 ++++
.../prototype/toString/offset-wrong-type.js | 22 ++++
.../toString/roundingmode-invalid-string.js | 10 ++
.../toString/roundingmode-undefined.js | 25 ++++
.../toString/roundingmode-wrong-type.js | 14 +++
.../toString/smallestunit-invalid-string.js | 10 ++
.../toString/smallestunit-undefined.js | 20 ++++
.../toString/smallestunit-wrong-type.js | 14 +++
.../toString/timezonename-invalid-string.js | 17 +++
.../toString/timezonename-undefined.js | 21 ++++
.../toString/timezonename-wrong-type.js | 22 ++++
.../until/largestunit-invalid-string.js | 11 ++
.../prototype/until/largestunit-undefined.js | 16 +++
.../prototype/until/largestunit-wrong-type.js | 15 +++
.../prototype/until/roundingincrement-nan.js | 18 +++
.../until/roundingincrement-undefined.js | 24 ++++
.../until/roundingincrement-wrong-type.js | 24 ++++
.../until/roundingmode-invalid-string.js | 11 ++
.../prototype/until/roundingmode-undefined.js | 26 +++++
.../until/roundingmode-wrong-type.js | 15 +++
.../until/smallestunit-invalid-string.js | 11 ++
.../prototype/until/smallestunit-undefined.js | 16 +++
.../until/smallestunit-wrong-type.js | 15 +++
.../with/disambiguation-invalid-string.js | 17 +++
.../with/disambiguation-undefined.js | 30 +++++
.../with/disambiguation-wrong-type.js | 21 ++++
.../prototype/with/offset-invalid-string.js | 17 +++
.../prototype/with/offset-undefined.js | 22 ++++
.../prototype/with/offset-wrong-type.js | 21 ++++
.../prototype/with/overflow-invalid-string.js | 20 ++++
.../prototype/with/overflow-undefined.js | 23 ++++
.../prototype/with/overflow-wrong-type.js | 45 ++++++++
polyfill/test/helpers/temporalHelpers.js | 108 ++++++++++++++++++
spec/abstractops.html | 91 ++++++---------
spec/intl.html | 52 ---------
365 files changed, 7357 insertions(+), 111 deletions(-)
create mode 100644 polyfill/test/Calendar/prototype/dateAdd/overflow-invalid-string.js
create mode 100644 polyfill/test/Calendar/prototype/dateAdd/overflow-undefined.js
create mode 100644 polyfill/test/Calendar/prototype/dateAdd/overflow-wrong-type.js
create mode 100644 polyfill/test/Calendar/prototype/dateFromFields/overflow-invalid-string.js
create mode 100644 polyfill/test/Calendar/prototype/dateFromFields/overflow-undefined.js
create mode 100644 polyfill/test/Calendar/prototype/dateFromFields/overflow-wrong-type.js
create mode 100644 polyfill/test/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js
create mode 100644 polyfill/test/Calendar/prototype/monthDayFromFields/overflow-undefined.js
create mode 100644 polyfill/test/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js
create mode 100644 polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js
create mode 100644 polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-undefined.js
create mode 100644 polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/round/largestunit-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/round/largestunit-undefined.js
create mode 100644 polyfill/test/Duration/prototype/round/largestunit-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingincrement-nan.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingincrement-undefined.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingmode-undefined.js
create mode 100644 polyfill/test/Duration/prototype/round/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/round/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/round/smallestunit-undefined.js
create mode 100644 polyfill/test/Duration/prototype/round/smallestunit-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-nan.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-non-integer.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-out-of-range.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-undefined.js
create mode 100644 polyfill/test/Duration/prototype/toString/fractionalseconddigits-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/toString/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/toString/roundingmode-undefined.js
create mode 100644 polyfill/test/Duration/prototype/toString/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/toString/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/toString/smallestunit-undefined.js
create mode 100644 polyfill/test/Duration/prototype/toString/smallestunit-wrong-type.js
create mode 100644 polyfill/test/Duration/prototype/total/unit-invalid-string.js
create mode 100644 polyfill/test/Duration/prototype/total/unit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingincrement-nan.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingincrement-undefined.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingmode-undefined.js
create mode 100644 polyfill/test/Instant/prototype/round/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/round/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/round/smallestunit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/Instant/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/Instant/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/Instant/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-nan.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-non-integer.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-out-of-range.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-undefined.js
create mode 100644 polyfill/test/Instant/prototype/toString/fractionalseconddigits-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/toString/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/toString/roundingmode-undefined.js
create mode 100644 polyfill/test/Instant/prototype/toString/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/toString/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/toString/smallestunit-undefined.js
create mode 100644 polyfill/test/Instant/prototype/toString/smallestunit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/Instant/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/Instant/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/Instant/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/Instant/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/Instant/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDate/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDate/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/PlainDate/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/add/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/add/overflow-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/add/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/subtract/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/subtract/overflow-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/subtract/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/toString/calendarname-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/toString/calendarname-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/toString/calendarname-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDate/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDate/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/PlainDate/prototype/with/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/PlainDateTime/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/add/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/add/overflow-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/add/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/round/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/subtract/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/subtract/overflow-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/subtract/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/calendarname-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/calendarname-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/calendarname-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toString/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainDateTime/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainDateTime/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/PlainDateTime/prototype/with/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainMonthDay/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainMonthDay/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/PlainMonthDay/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/toString/calendarname-invalid-string.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/toString/calendarname-undefined.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/toString/calendarname-wrong-type.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/PlainMonthDay/prototype/with/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainTime/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainTime/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/PlainTime/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/round/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/round/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/round/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-nan.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/toString/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainTime/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainTime/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/PlainTime/prototype/with/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/add/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/add/overflow-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/add/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/subtract/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/subtract/overflow-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/subtract/overflow-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/toString/calendarname-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/toString/calendarname-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/toString/calendarname-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/PlainYearMonth/prototype/with/overflow-wrong-type.js
create mode 100644 polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js
create mode 100644 polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-undefined.js
create mode 100644 polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/disambiguation-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/disambiguation-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/disambiguation-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/offset-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/offset-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/offset-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/overflow-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/overflow-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/constructor/from/overflow-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/add/overflow-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/add/overflow-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/add/overflow-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingincrement-nan.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingincrement-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingmode-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingmode-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/roundingmode-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/smallestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/round/smallestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/largestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/largestunit-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/largestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingincrement-nan.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingincrement-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingmode-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingmode-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/roundingmode-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/smallestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/smallestunit-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/since/smallestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/subtract/overflow-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/subtract/overflow-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/subtract/overflow-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/calendarname-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/calendarname-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/calendarname-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/offset-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/offset-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/offset-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/roundingmode-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/smallestunit-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/timezonename-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/timezonename-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/toString/timezonename-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/largestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/largestunit-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/largestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingincrement-nan.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingincrement-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingmode-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingmode-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/roundingmode-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/smallestunit-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/smallestunit-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/until/smallestunit-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/disambiguation-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/disambiguation-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/disambiguation-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/offset-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/offset-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/offset-wrong-type.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/overflow-invalid-string.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/overflow-undefined.js
create mode 100644 polyfill/test/ZonedDateTime/prototype/with/overflow-wrong-type.js
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 720afd967a..c2eb07fdde 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -680,8 +680,12 @@ export const ES = ObjectAssign({}, ES2020, {
default: // fall through if option not given
}
let digits = options.fractionalSecondDigits;
- if (digits === undefined || digits === 'auto') return { precision: 'auto', unit: 'nanosecond', increment: 1 };
- digits = ES.ToNumber(digits);
+ if (digits === undefined) digits = 'auto';
+ if (ES.Type(digits) !== 'Number') {
+ digits = ES.ToString(digits);
+ if (digits === 'auto') return { precision: 'auto', unit: 'nanosecond', increment: 1 };
+ throw new RangeError(`fractionalSecondDigits must be 'auto' or 0 through 9, not ${digits}`);
+ }
if (NumberIsNaN(digits) || digits < 0 || digits > 9) {
throw new RangeError(`fractionalSecondDigits must be 'auto' or 0 through 9, not ${digits}`);
}
diff --git a/polyfill/test/Calendar/prototype/dateAdd/overflow-invalid-string.js b/polyfill/test/Calendar/prototype/dateAdd/overflow-invalid-string.js
new file mode 100644
index 0000000000..0c9de8c17a
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateAdd/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.calendar.prototype.dateadd
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+const date = new Temporal.PlainDate(2000, 5, 2, calendar);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+assert.throws(RangeError, () => calendar.dateAdd(date, duration, { overflow: "other string" }));
diff --git a/polyfill/test/Calendar/prototype/dateAdd/overflow-undefined.js b/polyfill/test/Calendar/prototype/dateAdd/overflow-undefined.js
new file mode 100644
index 0000000000..5427f6483a
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateAdd/overflow-undefined.js
@@ -0,0 +1,24 @@
+// 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.calendar.prototype.dateadd
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+const date = new Temporal.PlainDate(2000, 5, 31, calendar);
+const duration = new Temporal.Duration(3, 1);
+
+const explicit = calendar.dateAdd(date, duration, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain");
+const implicit = calendar.dateAdd(date, duration, {});
+TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain");
diff --git a/polyfill/test/Calendar/prototype/dateAdd/overflow-wrong-type.js b/polyfill/test/Calendar/prototype/dateAdd/overflow-wrong-type.js
new file mode 100644
index 0000000000..4eb1f69e38
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateAdd/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.calendar.prototype.dateadd
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+const date = new Temporal.PlainDate(2000, 5, 2, calendar);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => calendar.dateAdd(date, duration, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr),
+);
diff --git a/polyfill/test/Calendar/prototype/dateFromFields/overflow-invalid-string.js b/polyfill/test/Calendar/prototype/dateFromFields/overflow-invalid-string.js
new file mode 100644
index 0000000000..daff07ea92
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateFromFields/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.calendar.prototype.datefromfields
+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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.datefromfields step 6:
+ 6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+assert.throws(RangeError, () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" }));
diff --git a/polyfill/test/Calendar/prototype/dateFromFields/overflow-undefined.js b/polyfill/test/Calendar/prototype/dateFromFields/overflow-undefined.js
new file mode 100644
index 0000000000..a9e6d4989b
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateFromFields/overflow-undefined.js
@@ -0,0 +1,24 @@
+// 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.calendar.prototype.datefromfields
+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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.datefromfields step 6:
+ 6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+
+const explicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain");
+const implicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, {});
+TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain");
diff --git a/polyfill/test/Calendar/prototype/dateFromFields/overflow-wrong-type.js b/polyfill/test/Calendar/prototype/dateFromFields/overflow-wrong-type.js
new file mode 100644
index 0000000000..74970ec6d9
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/dateFromFields/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.calendar.prototype.datefromfields
+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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.datefromfields step 6:
+ 6. Let _result_ be ? ISODateFromFields(_fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr),
+);
diff --git a/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js
new file mode 100644
index 0000000000..d298d5a152
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.calendar.prototype.monthdayfromfields
+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.calendar.prototype.monthdayfromfields step 6:
+ 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+assert.throws(RangeError, () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" }));
diff --git a/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-undefined.js b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-undefined.js
new file mode 100644
index 0000000000..8791b4fbc9
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-undefined.js
@@ -0,0 +1,24 @@
+// 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.calendar.prototype.monthdayfromfields
+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.calendar.prototype.monthdayfromfields step 6:
+ 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+
+const explicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined });
+TemporalHelpers.assertPlainMonthDay(explicit, "M12", 2, "default overflow is constrain");
+const implicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, {});
+TemporalHelpers.assertPlainMonthDay(implicit, "M12", 2, "default overflow is constrain");
diff --git a/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js
new file mode 100644
index 0000000000..5ec180ebff
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.calendar.prototype.monthdayfromfields
+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.calendar.prototype.monthdayfromfields step 6:
+ 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr),
+);
diff --git a/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js
new file mode 100644
index 0000000000..efea9dc253
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.calendar.prototype.yearmonthfromfields
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.yearmonthfromfields step 6:
+ 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+assert.throws(RangeError, () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow: "other string" }));
diff --git a/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-undefined.js b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-undefined.js
new file mode 100644
index 0000000000..eb5b8ac770
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-undefined.js
@@ -0,0 +1,24 @@
+// 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.calendar.prototype.yearmonthfromfields
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.yearmonthfromfields step 6:
+ 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+
+const explicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, { overflow: undefined });
+TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain");
+const implicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, {});
+TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain");
diff --git a/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js
new file mode 100644
index 0000000000..4a94915726
--- /dev/null
+++ b/polyfill/test/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.calendar.prototype.yearmonthfromfields
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.calendar.prototype.yearmonthfromfields step 6:
+ 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = new Temporal.Calendar("iso8601");
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr),
+);
diff --git a/polyfill/test/Duration/prototype/round/largestunit-invalid-string.js b/polyfill/test/Duration/prototype/round/largestunit-invalid-string.js
new file mode 100644
index 0000000000..7ab3ece6fe
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/largestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.duration.prototype.round
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => duration.round({ largestUnit: "other string" }));
diff --git a/polyfill/test/Duration/prototype/round/largestunit-undefined.js b/polyfill/test/Duration/prototype/round/largestunit-undefined.js
new file mode 100644
index 0000000000..19ee5c8540
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/largestunit-undefined.js
@@ -0,0 +1,20 @@
+// 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.duration.prototype.round
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const duration1 = new Temporal.Duration(0, 0, 0, 0, 1, 120, 1, 123, 456, 789);
+const explicit1 = duration1.round({ largestUnit: undefined, smallestUnit: "nanosecond" });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input");
+const implicit1 = duration1.round({ smallestUnit: "nanosecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 3, 0, 1, 123, 456, 789, "default largestUnit is largest in input");
+
+const duration2 = new Temporal.Duration(0, 0, 0, 0, 0, 120, 1, 123, 456, 789);
+const explicit2 = duration2.round({ largestUnit: undefined, smallestUnit: "nanosecond" });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input");
+const implicit2 = duration2.round({ smallestUnit: "nanosecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 120, 1, 123, 456, 789, "default largestUnit is largest in input");
diff --git a/polyfill/test/Duration/prototype/round/largestunit-wrong-type.js b/polyfill/test/Duration/prototype/round/largestunit-wrong-type.js
new file mode 100644
index 0000000000..44506cea23
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/largestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.round
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 456, 789);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "minute",
+ (largestUnit) => duration.round({ largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 754, 56, 123, 456, 789, descr),
+);
diff --git a/polyfill/test/Duration/prototype/round/roundingincrement-nan.js b/polyfill/test/Duration/prototype/round/roundingincrement-nan.js
new file mode 100644
index 0000000000..ded12bb469
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingincrement-nan.js
@@ -0,0 +1,17 @@
+// 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.duration.prototype.round
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.duration.prototype.round step 18:
+ 18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321);
+assert.throws(RangeError, () => duration.round({ smallestUnit: 'second', roundingIncrement: NaN }));
diff --git a/polyfill/test/Duration/prototype/round/roundingincrement-undefined.js b/polyfill/test/Duration/prototype/round/roundingincrement-undefined.js
new file mode 100644
index 0000000000..d15b354ce8
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingincrement-undefined.js
@@ -0,0 +1,23 @@
+// 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.duration.prototype.round
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.duration.prototype.round step 18:
+ 18. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321);
+
+const explicit = duration.round({ smallestUnit: 'second', roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
+
+const implicit = duration.round({ smallestUnit: 'second' });
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
diff --git a/polyfill/test/Duration/prototype/round/roundingincrement-wrong-type.js b/polyfill/test/Duration/prototype/round/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..57a452a6dd
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingincrement-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.plaintime.prototype.round
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.round step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 4, 12, 34, 56, 987, 654, 321);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => duration.round({ smallestUnit: 'second', roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 12, 34, 57, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 12, 34, 56, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/Duration/prototype/round/roundingmode-invalid-string.js b/polyfill/test/Duration/prototype/round/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..787262d32f
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.duration.prototype.round
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => duration.round({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Duration/prototype/round/roundingmode-undefined.js b/polyfill/test/Duration/prototype/round/roundingmode-undefined.js
new file mode 100644
index 0000000000..a10119f2fb
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.duration.prototype.round
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = duration.round({ smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+const implicit1 = duration.round({ smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+
+const explicit2 = duration.round({ smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+const implicit2 = duration.round({ smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+
+const explicit3 = duration.round({ smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
+const implicit3 = duration.round({ smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
diff --git a/polyfill/test/Duration/prototype/round/roundingmode-wrong-type.js b/polyfill/test/Duration/prototype/round/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..f868cc5a05
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.round
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand",
+ (roundingMode) => duration.round({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/Duration/prototype/round/smallestunit-invalid-string.js b/polyfill/test/Duration/prototype/round/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..d9ea817c06
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.duration.prototype.round
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => duration.round({ smallestUnit: "other string" }));
diff --git a/polyfill/test/Duration/prototype/round/smallestunit-undefined.js b/polyfill/test/Duration/prototype/round/smallestunit-undefined.js
new file mode 100644
index 0000000000..f37fa1baea
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/smallestunit-undefined.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.round
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 1, 2, 3, 123, 456, 789);
+const explicit1 = duration.round({ largestUnit: "day", smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 1, 2, 3, 123, 456, 789, "default smallestUnit is nanosecond");
+const implicit1 = duration.round({ largestUnit: "day" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 1, 2, 3, 123, 456, 789, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/Duration/prototype/round/smallestunit-wrong-type.js b/polyfill/test/Duration/prototype/round/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..f9330b26e8
--- /dev/null
+++ b/polyfill/test/Duration/prototype/round/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.round
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => duration.round({ smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-invalid-string.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-invalid-string.js
new file mode 100644
index 0000000000..6e95204089
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-invalid-string.js
@@ -0,0 +1,18 @@
+// 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.duration.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values
+info: |
+ sec-getstringornumberoption step 4:
+ 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+
+assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: "other string" }));
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-nan.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-nan.js
new file mode 100644
index 0000000000..1a667e4915
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-nan.js
@@ -0,0 +1,19 @@
+// 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.duration.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: NaN }));
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-non-integer.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-non-integer.js
new file mode 100644
index 0000000000..ad3f1e303b
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-non-integer.js
@@ -0,0 +1,19 @@
+// 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.duration.prototype.tostring
+description: Rounding for fractionalSecondDigits option
+info: |
+ sec-getstringornumberoption step 3.b:
+ b. Return floor(ℝ(_value_)).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+
+const string = duration.toString({ fractionalSecondDigits: 2.5 });
+assert.sameValue(string, "P1Y2M3W4DT5H6M7.98S", "fractionalSecondDigits 2.5 floors to 2");
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-out-of-range.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-out-of-range.js
new file mode 100644
index 0000000000..dd8056469f
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-out-of-range.js
@@ -0,0 +1,19 @@
+// 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.duration.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option out of range
+info: |
+ sec-getstringornumberoption step 3.a:
+ a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+
+assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -1 }));
+assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 10 }));
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-undefined.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-undefined.js
new file mode 100644
index 0000000000..aa136c9096
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-undefined.js
@@ -0,0 +1,24 @@
+// 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.duration.prototype.tostring
+description: Fallback value for fractionalSecondDigits option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+
+const explicit = duration.toString({ fractionalSecondDigits: undefined });
+assert.sameValue(explicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto");
+
+const implicit = duration.toString({});
+assert.sameValue(implicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto");
diff --git a/polyfill/test/Duration/prototype/toString/fractionalseconddigits-wrong-type.js b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-wrong-type.js
new file mode 100644
index 0000000000..3d7228e837
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/fractionalseconddigits-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.duration.prototype.tostring
+description: Type conversions for fractionalSecondDigits option
+info: |
+ sec-getoption steps 8–9:
+ 8. Else if _type_ is Number, then
+ a. Set _value_ to ? ToNumber(value).
+ b. ...
+ 9. Else,
+ a. Set _value_ to ? ToString(value).
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.duration.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0);
+TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(duration);
diff --git a/polyfill/test/Duration/prototype/toString/roundingmode-invalid-string.js b/polyfill/test/Duration/prototype/toString/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..6730656577
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.duration.prototype.tostring
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => duration.toString({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Duration/prototype/toString/roundingmode-undefined.js b/polyfill/test/Duration/prototype/toString/roundingmode-undefined.js
new file mode 100644
index 0000000000..d3bb5418c3
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.duration.prototype.tostring
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = duration.toString({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1, "PT12H34M56.123987S", "default roundingMode is trunc");
+const implicit1 = duration.toString({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1, "PT12H34M56.123987S", "default roundingMode is trunc");
+
+const explicit2 = duration.toString({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2, "PT12H34M56.123S", "default roundingMode is trunc");
+const implicit2 = duration.toString({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2, "PT12H34M56.123S", "default roundingMode is trunc");
+
+const explicit3 = duration.toString({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3, "PT12H34M56S", "default roundingMode is trunc");
+const implicit3 = duration.toString({ smallestUnit: "second" });
+assert.sameValue(implicit3, "PT12H34M56S", "default roundingMode is trunc");
diff --git a/polyfill/test/Duration/prototype/toString/roundingmode-wrong-type.js b/polyfill/test/Duration/prototype/toString/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..3d4986661e
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.tostring
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => duration.toString({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result, "PT12H34M56.123987S", descr),
+);
diff --git a/polyfill/test/Duration/prototype/toString/smallestunit-invalid-string.js b/polyfill/test/Duration/prototype/toString/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..c009fe1d72
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.duration.prototype.tostring
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => duration.toString({ smallestUnit: "other string" }));
diff --git a/polyfill/test/Duration/prototype/toString/smallestunit-undefined.js b/polyfill/test/Duration/prototype/toString/smallestunit-undefined.js
new file mode 100644
index 0000000000..1d87455f20
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/smallestunit-undefined.js
@@ -0,0 +1,20 @@
+// 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.duration.prototype.tostring
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = duration.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 });
+assert.sameValue(explicit1, "PT12H34M56.123987S", "default smallestUnit defers to fractionalSecondDigits");
+const implicit1 = duration.toString({ fractionalSecondDigits: 6 });
+assert.sameValue(implicit1, "PT12H34M56.123987S", "default smallestUnit defers to fractionalSecondDigits");
+
+const explicit2 = duration.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 });
+assert.sameValue(explicit2, "PT12H34M56.123S", "default smallestUnit defers to fractionalSecondDigits");
+const implicit2 = duration.toString({ fractionalSecondDigits: 3 });
+assert.sameValue(implicit2, "PT12H34M56.123S", "default smallestUnit defers to fractionalSecondDigits");
diff --git a/polyfill/test/Duration/prototype/toString/smallestunit-wrong-type.js b/polyfill/test/Duration/prototype/toString/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..fc8656df2c
--- /dev/null
+++ b/polyfill/test/Duration/prototype/toString/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.duration.prototype.tostring
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => duration.toString({ smallestUnit }),
+ (result, descr) => assert.sameValue(result, "PT12H34M56.123987S", descr),
+);
diff --git a/polyfill/test/Duration/prototype/total/unit-invalid-string.js b/polyfill/test/Duration/prototype/total/unit-invalid-string.js
new file mode 100644
index 0000000000..6e3bacf66f
--- /dev/null
+++ b/polyfill/test/Duration/prototype/total/unit-invalid-string.js
@@ -0,0 +1,17 @@
+// 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.duration.protoype.total
+description: RangeError thrown when unit 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-totemporaldurationtotal step 1:
+ 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*).
+ sec-temporal.duration.protoype.total step 5:
+ 5. Let _unit_ be ? ToTemporalDurationTotalUnit(_options_).
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 1);
+assert.throws(RangeError, () => duration.total({ unit: "other string" }));
diff --git a/polyfill/test/Duration/prototype/total/unit-wrong-type.js b/polyfill/test/Duration/prototype/total/unit-wrong-type.js
new file mode 100644
index 0000000000..444fc279a1
--- /dev/null
+++ b/polyfill/test/Duration/prototype/total/unit-wrong-type.js
@@ -0,0 +1,21 @@
+// 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.duration.prototype.total
+description: Type conversions for unit option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldurationtotal step 1:
+ 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*).
+ sec-temporal.duration.protoype.total step 5:
+ 5. Let _unit_ be ? ToTemporalDurationTotalUnit(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const duration = new Temporal.Duration(0, 0, 0, 1);
+TemporalHelpers.checkStringOptionWrongType("unit", "hour",
+ (unit) => duration.total({ unit }),
+ (result, descr) => assert.sameValue(result, 24, descr),
+);
diff --git a/polyfill/test/Instant/prototype/round/roundingincrement-nan.js b/polyfill/test/Instant/prototype/round/roundingincrement-nan.js
new file mode 100644
index 0000000000..82bfe34448
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingincrement-nan.js
@@ -0,0 +1,17 @@
+// 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.instant.prototype.round
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.round step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *true*).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+assert.throws(RangeError, () => instant.round({ smallestUnit: 'second', roundingIncrement: NaN }));
diff --git a/polyfill/test/Instant/prototype/round/roundingincrement-undefined.js b/polyfill/test/Instant/prototype/round/roundingincrement-undefined.js
new file mode 100644
index 0000000000..9017c8e131
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingincrement-undefined.js
@@ -0,0 +1,22 @@
+// 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.instant.prototype.round
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.round step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *true*).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+
+const explicit = instant.round({ smallestUnit: 'second', roundingIncrement: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1");
+
+const implicit = instant.round({ smallestUnit: 'second' });
+assert.sameValue(implicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1");
diff --git a/polyfill/test/Instant/prototype/round/roundingincrement-wrong-type.js b/polyfill/test/Instant/prototype/round/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..012103c36d
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingincrement-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.instant.prototype.round
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.round step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_654_321n);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => instant.round({ smallestUnit: 'second', roundingIncrement }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_001_000_000_000n, descr),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, descr),
+);
diff --git a/polyfill/test/Instant/prototype/round/roundingmode-invalid-string.js b/polyfill/test/Instant/prototype/round/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..c1cda5f049
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.instant.prototype.round
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+assert.throws(RangeError, () => instant.round({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Instant/prototype/round/roundingmode-undefined.js b/polyfill/test/Instant/prototype/round/roundingmode-undefined.js
new file mode 100644
index 0000000000..09c540131b
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.instant.prototype.round
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+
+const explicit1 = instant.round({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand");
+const implicit1 = instant.round({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand");
+
+const explicit2 = instant.round({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand");
+const implicit2 = instant.round({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand");
+
+const explicit3 = instant.round({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand");
+const implicit3 = instant.round({ smallestUnit: "second" });
+assert.sameValue(implicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand");
diff --git a/polyfill/test/Instant/prototype/round/roundingmode-wrong-type.js b/polyfill/test/Instant/prototype/round/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..13ad501318
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.instant.prototype.round
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand",
+ (roundingMode) => instant.round({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr),
+);
diff --git a/polyfill/test/Instant/prototype/round/smallestunit-invalid-string.js b/polyfill/test/Instant/prototype/round/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..e9e90ec680
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.instant.prototype.round
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+assert.throws(RangeError, () => instant.round({ smallestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/round/smallestunit-wrong-type.js b/polyfill/test/Instant/prototype/round/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..45b87d000c
--- /dev/null
+++ b/polyfill/test/Instant/prototype/round/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.instant.prototype.round
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => instant.round({ smallestUnit }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr),
+);
diff --git a/polyfill/test/Instant/prototype/since/largestunit-invalid-string.js b/polyfill/test/Instant/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..f22fc9da10
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/since/largestunit-undefined.js b/polyfill/test/Instant/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..4872a78eaa
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.instant.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second");
diff --git a/polyfill/test/Instant/prototype/since/largestunit-wrong-type.js b/polyfill/test/Instant/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..29549fc2fe
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "hour",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/Instant/prototype/since/roundingincrement-nan.js b/polyfill/test/Instant/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..dbbdbd592e
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.instant.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/Instant/prototype/since/roundingincrement-undefined.js b/polyfill/test/Instant/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..9d206bee1e
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/Instant/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/Instant/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..d6f0d4fc3e
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/Instant/prototype/since/roundingmode-invalid-string.js b/polyfill/test/Instant/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..cefc4a4073
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Instant/prototype/since/roundingmode-undefined.js b/polyfill/test/Instant/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..a9d7ad9e1b
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// 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.instant.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+
+const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = later.since(earlier, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = later.since(earlier, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = later.since(earlier, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/Instant/prototype/since/roundingmode-wrong-type.js b/polyfill/test/Instant/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..501237e670
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/Instant/prototype/since/smallestunit-invalid-string.js b/polyfill/test/Instant/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..0b48766d10
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/since/smallestunit-undefined.js b/polyfill/test/Instant/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..68d7d651e7
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.instant.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/Instant/prototype/since/smallestunit-wrong-type.js b/polyfill/test/Instant/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..f719b921e4
--- /dev/null
+++ b/polyfill/test/Instant/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-invalid-string.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-invalid-string.js
new file mode 100644
index 0000000000..fcc02fff54
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-invalid-string.js
@@ -0,0 +1,18 @@
+// 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.instant.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values
+info: |
+ sec-getstringornumberoption step 4:
+ 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+
+assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: "other string" }));
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-nan.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-nan.js
new file mode 100644
index 0000000000..9d4c068694
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-nan.js
@@ -0,0 +1,20 @@
+// 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.instant.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: NaN }));
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-non-integer.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-non-integer.js
new file mode 100644
index 0000000000..f469090ab6
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-non-integer.js
@@ -0,0 +1,19 @@
+// 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.instant.prototype.tostring
+description: Rounding for fractionalSecondDigits option
+info: |
+ sec-getstringornumberoption step 3.b:
+ b. Return floor(ℝ(_value_)).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+
+const string = instant.toString({ fractionalSecondDigits: 2.5 });
+assert.sameValue(string, "2001-09-09T01:46:40.98Z", "fractionalSecondDigits 2.5 floors to 2");
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-out-of-range.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-out-of-range.js
new file mode 100644
index 0000000000..5ffa45a662
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-out-of-range.js
@@ -0,0 +1,19 @@
+// 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.instant.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option out of range
+info: |
+ sec-getstringornumberoption step 3.a:
+ a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+
+assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -1 }));
+assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: 10 }));
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-undefined.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-undefined.js
new file mode 100644
index 0000000000..45418d7f0d
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-undefined.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.tostring
+description: Fallback value for fractionalSecondDigits option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+
+const explicit = instant.toString({ fractionalSecondDigits: undefined });
+assert.sameValue(explicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto");
+
+const implicit = instant.toString({});
+assert.sameValue(implicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto");
diff --git a/polyfill/test/Instant/prototype/toString/fractionalseconddigits-wrong-type.js b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-wrong-type.js
new file mode 100644
index 0000000000..591b435861
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/fractionalseconddigits-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.tostring
+description: Type conversions for fractionalSecondDigits option
+info: |
+ sec-getoption steps 8–9:
+ 8. Else if _type_ is Number, then
+ a. Set _value_ to ? ToNumber(value).
+ b. ...
+ 9. Else,
+ a. Set _value_ to ? ToString(value).
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 6:
+ 6. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_987_650_000n);
+TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(instant);
diff --git a/polyfill/test/Instant/prototype/toString/roundingmode-invalid-string.js b/polyfill/test/Instant/prototype/toString/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..6423b5607c
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.instant.prototype.tostring
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+assert.throws(RangeError, () => instant.toString({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Instant/prototype/toString/roundingmode-undefined.js b/polyfill/test/Instant/prototype/toString/roundingmode-undefined.js
new file mode 100644
index 0000000000..4299b031cf
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.instant.prototype.tostring
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+
+const explicit1 = instant.toString({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1, "2001-09-09T01:46:40.123987Z", "default roundingMode is trunc");
+const implicit1 = instant.toString({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1, "2001-09-09T01:46:40.123987Z", "default roundingMode is trunc");
+
+const explicit2 = instant.toString({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2, "2001-09-09T01:46:40.123Z", "default roundingMode is trunc");
+const implicit2 = instant.toString({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2, "2001-09-09T01:46:40.123Z", "default roundingMode is trunc");
+
+const explicit3 = instant.toString({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3, "2001-09-09T01:46:40Z", "default roundingMode is trunc");
+const implicit3 = instant.toString({ smallestUnit: "second" });
+assert.sameValue(implicit3, "2001-09-09T01:46:40Z", "default roundingMode is trunc");
diff --git a/polyfill/test/Instant/prototype/toString/roundingmode-wrong-type.js b/polyfill/test/Instant/prototype/toString/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..56a81dbc60
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.instant.prototype.tostring
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => instant.toString({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987Z", descr),
+);
diff --git a/polyfill/test/Instant/prototype/toString/smallestunit-invalid-string.js b/polyfill/test/Instant/prototype/toString/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..ce03840c31
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.instant.prototype.tostring
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+assert.throws(RangeError, () => instant.toString({ smallestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/toString/smallestunit-undefined.js b/polyfill/test/Instant/prototype/toString/smallestunit-undefined.js
new file mode 100644
index 0000000000..d7ac3c9ea0
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/smallestunit-undefined.js
@@ -0,0 +1,20 @@
+// 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.instant.prototype.tostring
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+
+const explicit1 = instant.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 });
+assert.sameValue(explicit1, "2001-09-09T01:46:40.123987Z", "default smallestUnit defers to fractionalSecondDigits");
+const implicit1 = instant.toString({ fractionalSecondDigits: 6 });
+assert.sameValue(implicit1, "2001-09-09T01:46:40.123987Z", "default smallestUnit defers to fractionalSecondDigits");
+
+const explicit2 = instant.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 });
+assert.sameValue(explicit2, "2001-09-09T01:46:40.123Z", "default smallestUnit defers to fractionalSecondDigits");
+const implicit2 = instant.toString({ fractionalSecondDigits: 3 });
+assert.sameValue(implicit2, "2001-09-09T01:46:40.123Z", "default smallestUnit defers to fractionalSecondDigits");
diff --git a/polyfill/test/Instant/prototype/toString/smallestunit-wrong-type.js b/polyfill/test/Instant/prototype/toString/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..aba6cdbc26
--- /dev/null
+++ b/polyfill/test/Instant/prototype/toString/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.instant.prototype.tostring
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const instant = new Temporal.Instant(1_000_000_000_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => instant.toString({ smallestUnit }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987Z", descr),
+);
diff --git a/polyfill/test/Instant/prototype/until/largestunit-invalid-string.js b/polyfill/test/Instant/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..0bdb5d5e5c
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/until/largestunit-undefined.js b/polyfill/test/Instant/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..8fb2c8ad66
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.instant.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default largestUnit is second");
diff --git a/polyfill/test/Instant/prototype/until/largestunit-wrong-type.js b/polyfill/test/Instant/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..5e45370bc7
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "hour",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/Instant/prototype/until/roundingincrement-nan.js b/polyfill/test/Instant/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..a12c84a83b
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.instant.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/Instant/prototype/until/roundingincrement-undefined.js b/polyfill/test/Instant/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..c48b63e455
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/Instant/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/Instant/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..5134ca6273
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.instant.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.instant.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_987_654_321n);
+const later = new Temporal.Instant(1_000_090_061_988_655_322n);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/Instant/prototype/until/roundingmode-invalid-string.js b/polyfill/test/Instant/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..6c4a52f610
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/Instant/prototype/until/roundingmode-undefined.js b/polyfill/test/Instant/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..de1902e666
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// 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.instant.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+
+const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 0, 0, 90061, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = earlier.until(later, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 0, 0, 90061, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/Instant/prototype/until/roundingmode-wrong-type.js b/polyfill/test/Instant/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..a3df3c3483
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_123_987_500n);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/Instant/prototype/until/smallestunit-invalid-string.js b/polyfill/test/Instant/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..1b4bd59212
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.instant.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/Instant/prototype/until/smallestunit-undefined.js b/polyfill/test/Instant/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..d5bc00d2f5
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.instant.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/Instant/prototype/until/smallestunit-wrong-type.js b/polyfill/test/Instant/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..0b332ae257
--- /dev/null
+++ b/polyfill/test/Instant/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.instant.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.Instant(1_000_000_000_000_000_000n);
+const later = new Temporal.Instant(1_000_090_061_987_654_321n);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 90061, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/constructor/from/overflow-invalid-string.js b/polyfill/test/PlainDate/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..05e1b46bfc
--- /dev/null
+++ b/polyfill/test/PlainDate/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,31 @@
+// 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.plaindate.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-totemporaldate steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Return ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDate(_item_, _options_).
+---*/
+
+const validValues = [
+ new Temporal.PlainDate(2000, 5, 2),
+ { year: 2000, month: 5, day: 2 },
+ "2000-05-02",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.PlainDate.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/PlainDate/constructor/from/overflow-undefined.js b/polyfill/test/PlainDate/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..3ad0acfdf9
--- /dev/null
+++ b/polyfill/test/PlainDate/constructor/from/overflow-undefined.js
@@ -0,0 +1,40 @@
+// 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.plaindate.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-totemporaldate steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Return ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDate(_item_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainDate(2000, 5, 2),
+ "2000-05-02",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.PlainDate.from(value, { overflow: undefined });
+ TemporalHelpers.assertPlainDate(explicit, 2000, 5, "M05", 2, "overflow is ignored");
+ const implicit = Temporal.PlainDate.from(value, {});
+ TemporalHelpers.assertPlainDate(implicit, 2000, 5, "M05", 2, "overflow is ignored");
+});
+
+const propertyBag = { year: 2000, month: 13, day: 34 };
+const explicit = Temporal.PlainDate.from(propertyBag, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 31, "default overflow is constrain");
+const implicit = Temporal.PlainDate.from(propertyBag, {});
+TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 31, "default overflow is constrain");
diff --git a/polyfill/test/PlainDate/constructor/from/overflow-wrong-type.js b/polyfill/test/PlainDate/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..4786cf7149
--- /dev/null
+++ b/polyfill/test/PlainDate/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,33 @@
+// 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.plaindate.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-totemporaldate steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Return ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDate]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDate(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainDate(2000, 5, 2),
+ { year: 2000, month: 5, day: 2 },
+ "2000-05-02",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.PlainDate.from(value, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr),
+));
diff --git a/polyfill/test/PlainDate/prototype/add/overflow-invalid-string.js b/polyfill/test/PlainDate/prototype/add/overflow-invalid-string.js
new file mode 100644
index 0000000000..f19aaa9e22
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/add/overflow-invalid-string.js
@@ -0,0 +1,20 @@
+// 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.plaindate.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.add step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_).
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+assert.throws(RangeError, () => date.add(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/add/overflow-undefined.js b/polyfill/test/PlainDate/prototype/add/overflow-undefined.js
new file mode 100644
index 0000000000..3d97645f38
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/add/overflow-undefined.js
@@ -0,0 +1,25 @@
+// 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.plaindate.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.add step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 31);
+const duration = new Temporal.Duration(3, 1);
+
+const explicit = date.add(duration, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain");
+const implicit = date.add(duration, {});
+TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain");
diff --git a/polyfill/test/PlainDate/prototype/add/overflow-wrong-type.js b/polyfill/test/PlainDate/prototype/add/overflow-wrong-type.js
new file mode 100644
index 0000000000..5f2718fb49
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/add/overflow-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaindate.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.add step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _balancedDuration_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => date.add(duration, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/since/largestunit-invalid-string.js b/polyfill/test/PlainDate/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..7841166fa9
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/since/largestunit-undefined.js b/polyfill/test/PlainDate/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..20aa4a5ae5
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaindate.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day");
diff --git a/polyfill/test/PlainDate/prototype/since/largestunit-wrong-type.js b/polyfill/test/PlainDate/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..a86f1bb652
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/since/roundingincrement-nan.js b/polyfill/test/PlainDate/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..f06c9edf98
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plaindate.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.since step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainDate/prototype/since/roundingincrement-undefined.js b/polyfill/test/PlainDate/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..27b50569b2
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,23 @@
+// 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.plaindate.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.since step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/PlainDate/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/PlainDate/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..5ed0b16f9d
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaindate.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.since step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/since/roundingmode-invalid-string.js b/polyfill/test/PlainDate/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..84fdc59f62
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/since/roundingmode-undefined.js b/polyfill/test/PlainDate/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..9e7090830b
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,22 @@
+// 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.plaindate.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 1, 1);
+
+const later1 = new Temporal.PlainDate(2005, 2, 20);
+const explicit1 = later1.since(earlier, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit1 = later1.since(earlier, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+
+const later2 = new Temporal.PlainDate(2005, 12, 15);
+const explicit2 = later2.since(earlier, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit2 = later2.since(earlier, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainDate/prototype/since/roundingmode-wrong-type.js b/polyfill/test/PlainDate/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..031d8204cc
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "year", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/since/smallestunit-invalid-string.js b/polyfill/test/PlainDate/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..d42f74c2ed
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/since/smallestunit-undefined.js b/polyfill/test/PlainDate/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..1d23829420
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaindate.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day");
diff --git a/polyfill/test/PlainDate/prototype/since/smallestunit-wrong-type.js b/polyfill/test/PlainDate/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..d455422964
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/subtract/overflow-invalid-string.js b/polyfill/test/PlainDate/prototype/subtract/overflow-invalid-string.js
new file mode 100644
index 0000000000..73fefcd86f
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/subtract/overflow-invalid-string.js
@@ -0,0 +1,20 @@
+// 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.plaindate.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.subtract step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_).
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+assert.throws(RangeError, () => date.subtract(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/subtract/overflow-undefined.js b/polyfill/test/PlainDate/prototype/subtract/overflow-undefined.js
new file mode 100644
index 0000000000..843e7ebf37
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/subtract/overflow-undefined.js
@@ -0,0 +1,25 @@
+// 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.plaindate.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.subtract step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 31);
+const duration = new Temporal.Duration(3, 1);
+
+const explicit = date.subtract(duration, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 1997, 4, "M04", 30, "default overflow is constrain");
+const implicit = date.subtract(duration, {});
+TemporalHelpers.assertPlainDate(implicit, 1997, 4, "M04", 30, "default overflow is constrain");
diff --git a/polyfill/test/PlainDate/prototype/subtract/overflow-wrong-type.js b/polyfill/test/PlainDate/prototype/subtract/overflow-wrong-type.js
new file mode 100644
index 0000000000..257a7f9a04
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/subtract/overflow-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaindate.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.subtract step 7:
+ 7. Return ? CalendarDateAdd(_temporalDate_.[[Calendar]], _temporalDate_, _negatedDuration_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+const duration = new Temporal.Duration(3, 3, 0, 3);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => date.subtract(duration, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 1997, 1, "M01", 30, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/toString/calendarname-invalid-string.js b/polyfill/test/PlainDate/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..55db785ebb
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/toString/calendarname-invalid-string.js
@@ -0,0 +1,17 @@
+// 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.plaindate.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"* », *"auto"*).
+ sec-temporal.plaindate.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+assert.throws(RangeError, () => date.toString({ calendarName: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/toString/calendarname-undefined.js b/polyfill/test/PlainDate/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..f525ce793c
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,31 @@
+// 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.plaindate.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"* », *"auto"*).
+ sec-temporal.plaindate.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const date1 = new Temporal.PlainDate(2000, 5, 2);
+const date2 = new Temporal.PlainDate(2000, 5, 2, calendar);
+
+[
+ [date1, "2000-05-02"],
+ [date2, "2000-05-02[u-ca=custom]"],
+].forEach(([date, expected]) => {
+ const explicit = date.toString({ calendarName: undefined });
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ const implicit = date.toString({});
+ assert.sameValue(implicit, expected, "default calendarName option is auto");
+});
diff --git a/polyfill/test/PlainDate/prototype/toString/calendarname-wrong-type.js b/polyfill/test/PlainDate/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..d06e6be596
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,25 @@
+// 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.plaindate.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"* », *"auto"*).
+ sec-temporal.plaindate.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const date = new Temporal.PlainDate(2000, 5, 2, calendar);
+
+TemporalHelpers.checkStringOptionWrongType("calendarName", "auto",
+ (calendarName) => date.toString({ calendarName }),
+ (result, descr) => assert.sameValue(result, "2000-05-02[u-ca=custom]", descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/until/largestunit-invalid-string.js b/polyfill/test/PlainDate/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..9afc6edf88
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/until/largestunit-undefined.js b/polyfill/test/PlainDate/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..e29f14aac4
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaindate.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day");
diff --git a/polyfill/test/PlainDate/prototype/until/largestunit-wrong-type.js b/polyfill/test/PlainDate/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..6e43225aa2
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/until/roundingincrement-nan.js b/polyfill/test/PlainDate/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..3580031e92
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plaindate.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainDate/prototype/until/roundingincrement-undefined.js b/polyfill/test/PlainDate/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..b79a5cdf3a
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,23 @@
+// 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.plaindate.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/PlainDate/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/PlainDate/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..56bc87d76f
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaindate.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindate.prototype.until step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2000, 5, 7);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/until/roundingmode-invalid-string.js b/polyfill/test/PlainDate/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..9b0dd99dc2
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/until/roundingmode-undefined.js b/polyfill/test/PlainDate/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..faf945f352
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,22 @@
+// 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.plaindate.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 1, 1);
+
+const later1 = new Temporal.PlainDate(2005, 2, 20);
+const explicit1 = earlier.until(later1, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later1, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+
+const later2 = new Temporal.PlainDate(2005, 12, 15);
+const explicit2 = earlier.until(later2, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later2, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainDate/prototype/until/roundingmode-wrong-type.js b/polyfill/test/PlainDate/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..080227140f
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "year", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/until/smallestunit-invalid-string.js b/polyfill/test/PlainDate/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..750b37f963
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaindate.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/until/smallestunit-undefined.js b/polyfill/test/PlainDate/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..b8bc9bf291
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaindate.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day");
diff --git a/polyfill/test/PlainDate/prototype/until/smallestunit-wrong-type.js b/polyfill/test/PlainDate/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..5265a3d919
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaindate.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDate(2000, 5, 2);
+const later = new Temporal.PlainDate(2001, 6, 3);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDate/prototype/with/overflow-invalid-string.js b/polyfill/test/PlainDate/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..5552c6cdc3
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.plaindate.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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.with step 16:
+ 16. Return ? DateFromFields(_calendar_, _fields_, _options_).
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+assert.throws(RangeError, () => date.with({ month: 8 }, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDate/prototype/with/overflow-undefined.js b/polyfill/test/PlainDate/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..b3eab440df
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/with/overflow-undefined.js
@@ -0,0 +1,23 @@
+// 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.plaindate.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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.with step 16:
+ 16. Return ? DateFromFields(_calendar_, _fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+const explicit = date.with({ month: 15 }, { overflow: undefined });
+TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain");
+const implicit = date.with({ month: 15 }, {});
+TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain");
diff --git a/polyfill/test/PlainDate/prototype/with/overflow-wrong-type.js b/polyfill/test/PlainDate/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..13bb235623
--- /dev/null
+++ b/polyfill/test/PlainDate/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.plaindate.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-isodatefromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindate.prototype.with step 16:
+ 16. Return ? DateFromFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const date = new Temporal.PlainDate(2000, 5, 2);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => date.with({ month: 8 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 8, "M08", 2, descr),
+);
diff --git a/polyfill/test/PlainDateTime/constructor/from/overflow-invalid-string.js b/polyfill/test/PlainDateTime/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..8aaf6d655d
--- /dev/null
+++ b/polyfill/test/PlainDateTime/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporaldatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDateTime(_item_, _options_).
+---*/
+
+const validValues = [
+ new Temporal.PlainDateTime(2000, 5, 2, 12),
+ { year: 2000, month: 5, day: 2, hour: 12 },
+ "2000-05-02T12:00",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.PlainDateTime.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/PlainDateTime/constructor/from/overflow-undefined.js b/polyfill/test/PlainDateTime/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..d0c7d6571b
--- /dev/null
+++ b/polyfill/test/PlainDateTime/constructor/from/overflow-undefined.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporaldatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDateTime(_item_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainDateTime(2000, 5, 2, 12),
+ "2000-05-02T12:00",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.PlainDateTime.from(value, { overflow: undefined });
+ TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "overflow is ignored");
+ const implicit = Temporal.PlainDateTime.from(value, {});
+ TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "overflow is ignored");
+});
+
+const propertyBag = { year: 2000, month: 13, day: 34, hour: 12 };
+const explicit = Temporal.PlainDateTime.from(propertyBag, { overflow: undefined });
+TemporalHelpers.assertPlainDateTime(explicit, 2000, 12, "M12", 31, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = Temporal.PlainDateTime.from(propertyBag, {});
+TemporalHelpers.assertPlainDateTime(implicit, 2000, 12, "M12", 31, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainDateTime/constructor/from/overflow-wrong-type.js b/polyfill/test/PlainDateTime/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..922f9a1723
--- /dev/null
+++ b/polyfill/test/PlainDateTime/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporaldatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalDateTime(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainDateTime(2000, 5, 2, 12),
+ "2000-05-02T12:00",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.PlainDateTime.from(value, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, descr),
+));
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+const propertyBag = { year: 2000, month: 5, day: 2, hour: 12 };
+
+assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: null }), "null");
+assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: true }), "true");
+assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: false }), "false");
+assert.throws(TypeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => Temporal.PlainDateTime.from(propertyBag, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateFromFields() in the builtin
+// calendars, to get the option value for the date part, and then once again
+// internally to get the option value for the time part.
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = Temporal.PlainDateTime.from(propertyBag, { overflow: observer });
+TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/PlainDateTime/prototype/add/overflow-invalid-string.js b/polyfill/test/PlainDateTime/prototype/add/overflow-invalid-string.js
new file mode 100644
index 0000000000..33e2d66b61
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/add/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.add step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+const duration = new Temporal.Duration(3, 3, 0, 3, 3);
+assert.throws(RangeError, () => datetime.add(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/add/overflow-undefined.js b/polyfill/test/PlainDateTime/prototype/add/overflow-undefined.js
new file mode 100644
index 0000000000..0dd21fcb8d
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/add/overflow-undefined.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.add step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 31, 12);
+const duration = new Temporal.Duration(3, 1);
+
+const explicit = datetime.add(duration, { overflow: undefined });
+TemporalHelpers.assertPlainDateTime(explicit, 2003, 6, "M06", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = datetime.add(duration, {});
+TemporalHelpers.assertPlainDateTime(implicit, 2003, 6, "M06", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainDateTime/prototype/add/overflow-wrong-type.js b/polyfill/test/PlainDateTime/prototype/add/overflow-wrong-type.js
new file mode 100644
index 0000000000..0a6f014ed9
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/add/overflow-wrong-type.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.add step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+const duration = new Temporal.Duration(3, 3, 0, 3, 3);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => datetime.add(duration, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2003, 8, "M08", 5, 15, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingincrement-nan.js b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-nan.js
new file mode 100644
index 0000000000..8b945d2115
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-nan.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.plaindatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+assert.throws(RangeError, () => datetime.round({ smallestUnit: 'second', roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingincrement-undefined.js b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-undefined.js
new file mode 100644
index 0000000000..8ef17df2e9
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.plaindatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+
+const explicit = datetime.round({ smallestUnit: 'second', roundingIncrement: undefined });
+TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
+
+const implicit = datetime.round({ smallestUnit: 'second' });
+TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingincrement-wrong-type.js b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..57165b484f
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingincrement-wrong-type.js
@@ -0,0 +1,25 @@
+// 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.plaintime.prototype.round
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.plaindatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => datetime.round({ smallestUnit: 'second', roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 57, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingmode-invalid-string.js b/polyfill/test/PlainDateTime/prototype/round/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..852fea7bee
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingmode-undefined.js b/polyfill/test/PlainDateTime/prototype/round/roundingmode-undefined.js
new file mode 100644
index 0000000000..a5fc311bab
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = datetime.round({ smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertPlainDateTime(explicit1, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+const implicit1 = datetime.round({ smallestUnit: "microsecond" });
+TemporalHelpers.assertPlainDateTime(implicit1, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+
+const explicit2 = datetime.round({ smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertPlainDateTime(explicit2, 2000, 5, "M05", 2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+const implicit2 = datetime.round({ smallestUnit: "millisecond" });
+TemporalHelpers.assertPlainDateTime(implicit2, 2000, 5, "M05", 2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+
+const explicit3 = datetime.round({ smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertPlainDateTime(explicit3, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
+const implicit3 = datetime.round({ smallestUnit: "second" });
+TemporalHelpers.assertPlainDateTime(implicit3, 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
diff --git a/polyfill/test/PlainDateTime/prototype/round/roundingmode-wrong-type.js b/polyfill/test/PlainDateTime/prototype/round/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..457c73a015
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand",
+ (roundingMode) => datetime.round({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/round/smallestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/round/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..9c252c378d
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/round/smallestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/round/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..19973a328b
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/round/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.round
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => datetime.round({ smallestUnit }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/since/largestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..dd6ea463c9
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/since/largestunit-undefined.js b/polyfill/test/PlainDateTime/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..0a6cc39d21
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day");
diff --git a/polyfill/test/PlainDateTime/prototype/since/largestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..4893d62087
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 1, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingincrement-nan.js b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..c7f0c89477
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.since step 13:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingincrement-undefined.js b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..3708a1998a
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..d16355f11c
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingmode-invalid-string.js b/polyfill/test/PlainDateTime/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..4ff26aec67
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingmode-undefined.js b/polyfill/test/PlainDateTime/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..c488d587db
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+
+const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = later.since(earlier, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = later.since(earlier, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = later.since(earlier, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainDateTime/prototype/since/roundingmode-wrong-type.js b/polyfill/test/PlainDateTime/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..d23743be68
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/since/smallestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..7560d1e562
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/since/smallestunit-undefined.js b/polyfill/test/PlainDateTime/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..7bc5dc37ea
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/PlainDateTime/prototype/since/smallestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..bc7afa9f45
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/subtract/overflow-invalid-string.js b/polyfill/test/PlainDateTime/prototype/subtract/overflow-invalid-string.js
new file mode 100644
index 0000000000..9ae3923498
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/subtract/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.subtract step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+---*/
+
+const date = new Temporal.PlainDateTime(2000, 5, 2, 12);
+const duration = new Temporal.Duration(3, 3, 0, 3, 3);
+assert.throws(RangeError, () => date.subtract(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/subtract/overflow-undefined.js b/polyfill/test/PlainDateTime/prototype/subtract/overflow-undefined.js
new file mode 100644
index 0000000000..c69e4503db
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/subtract/overflow-undefined.js
@@ -0,0 +1,27 @@
+// 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.plaindate.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.subtract step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 31, 12);
+const duration = new Temporal.Duration(3, 1);
+
+const explicit = datetime.subtract(duration, { overflow: undefined });
+TemporalHelpers.assertPlainDateTime(explicit, 1997, 4, "M04", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = datetime.subtract(duration, {});
+TemporalHelpers.assertPlainDateTime(implicit, 1997, 4, "M04", 30, 12, 0, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainDateTime/prototype/subtract/overflow-wrong-type.js b/polyfill/test/PlainDateTime/prototype/subtract/overflow-wrong-type.js
new file mode 100644
index 0000000000..d9c68998db
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/subtract/overflow-wrong-type.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-adddatetime step 4:
+ 4. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.plaindatetime.prototype.subtract step 5:
+ 5. Let _result_ be ? AddDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _dateTime_.[[Calendar]], −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+const duration = new Temporal.Duration(3, 3, 0, 3, 3);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => datetime.subtract(duration, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainDateTime(result, 1997, 1, "M01", 30, 9, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/toString/calendarname-invalid-string.js b/polyfill/test/PlainDateTime/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..26b8320c6e
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/calendarname-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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"* », *"auto"*).
+ sec-temporal.plaindatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+assert.throws(RangeError, () => datetime.toString({ calendarName: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/calendarname-undefined.js b/polyfill/test/PlainDateTime/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..27558f341e
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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"* », *"auto"*).
+ sec-temporal.plaindatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const datetime1 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const datetime2 = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
+
+[
+ [datetime1, "2000-05-02T12:34:56.987654321"],
+ [datetime2, "2000-05-02T12:34:56.987654321[u-ca=custom]"],
+].forEach(([datetime, expected]) => {
+ const explicit = datetime.toString({ calendarName: undefined });
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ // See options-undefined.js for {}
+});
diff --git a/polyfill/test/PlainDateTime/prototype/toString/calendarname-wrong-type.js b/polyfill/test/PlainDateTime/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..fc1aa74152
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.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"* », *"auto"*).
+ sec-temporal.plaindatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
+
+TemporalHelpers.checkStringOptionWrongType("calendarName", "auto",
+ (calendarName) => datetime.toString({ calendarName }),
+ (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.987654321[u-ca=custom]", descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
new file mode 100644
index 0000000000..dbfad22afe
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values
+info: |
+ sec-getstringornumberoption step 4:
+ 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js
new file mode 100644
index 0000000000..117c605ab7
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-nan.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: NaN }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js
new file mode 100644
index 0000000000..4e880d612a
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Rounding for fractionalSecondDigits option
+info: |
+ sec-getstringornumberoption step 3.b:
+ b. Return floor(ℝ(_value_)).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+
+const string = datetime.toString({ fractionalSecondDigits: 2.5 });
+assert.sameValue(string, "2000-05-02T12:34:56.98", "fractionalSecondDigits 2.5 floors to 2");
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
new file mode 100644
index 0000000000..42b2738515
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option out of range
+info: |
+ sec-getstringornumberoption step 3.a:
+ a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 }));
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js
new file mode 100644
index 0000000000..c82d108721
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Fallback value for fractionalSecondDigits option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+
+const explicit = datetime.toString({ fractionalSecondDigits: undefined });
+assert.sameValue(explicit, "2000-05-02T12:34:56.98765", "default fractionalSecondDigits is auto");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
new file mode 100644
index 0000000000..dcdc868a11
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Type conversions for fractionalSecondDigits option
+info: |
+ sec-getoption steps 8–9:
+ 8. Else if _type_ is Number, then
+ a. Set _value_ to ? ToNumber(value).
+ b. ...
+ 9. Else,
+ a. Set _value_ to ? ToString(value).
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaindatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0);
+TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime);
diff --git a/polyfill/test/PlainDateTime/prototype/toString/roundingmode-invalid-string.js b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..eb334b35ad
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/roundingmode-undefined.js b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-undefined.js
new file mode 100644
index 0000000000..d9281dc281
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1, "2000-05-02T12:34:56.123987", "default roundingMode is trunc");
+const implicit1 = datetime.toString({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1, "2000-05-02T12:34:56.123987", "default roundingMode is trunc");
+
+const explicit2 = datetime.toString({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2, "2000-05-02T12:34:56.123", "default roundingMode is trunc");
+const implicit2 = datetime.toString({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2, "2000-05-02T12:34:56.123", "default roundingMode is trunc");
+
+const explicit3 = datetime.toString({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3, "2000-05-02T12:34:56", "default roundingMode is trunc");
+const implicit3 = datetime.toString({ smallestUnit: "second" });
+assert.sameValue(implicit3, "2000-05-02T12:34:56", "default roundingMode is trunc");
diff --git a/polyfill/test/PlainDateTime/prototype/toString/roundingmode-wrong-type.js b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..38e4b0f03e
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => datetime.toString({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.123987", descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/toString/smallestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..2709cb19ac
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/toString/smallestunit-undefined.js b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-undefined.js
new file mode 100644
index 0000000000..51bcc66fa2
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-undefined.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+
+const explicit1 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 });
+assert.sameValue(explicit1, "2000-05-02T12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits");
+const implicit1 = datetime.toString({ fractionalSecondDigits: 6 });
+assert.sameValue(implicit1, "2000-05-02T12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits");
+
+const explicit2 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 });
+assert.sameValue(explicit2, "2000-05-02T12:34:56.123", "default smallestUnit defers to fractionalSecondDigits");
+const implicit2 = datetime.toString({ fractionalSecondDigits: 3 });
+assert.sameValue(implicit2, "2000-05-02T12:34:56.123", "default smallestUnit defers to fractionalSecondDigits");
diff --git a/polyfill/test/PlainDateTime/prototype/toString/smallestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..2ec84f94ea
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toString/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tostring
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => datetime.toString({ smallestUnit }),
+ (result, descr) => assert.sameValue(result, "2000-05-02T12:34:56.123987", descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..16075636d0
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-invalid-string.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tozoneddatetime
+description: RangeError thrown when disambiguation option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.plaindatetime.prototype.tozoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+assert.throws(RangeError, () => datetime.toZonedDateTime(timeZone, { disambiguation: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js
new file mode 100644
index 0000000000..4f663ae36f
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-undefined.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tozoneddatetime
+description: Fallback value for disambiguation option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.plaindatetime.prototype.tozoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardDatetime = new Temporal.PlainDateTime(2000, 4, 2, 2, 30);
+const fallBackDatetime = new Temporal.PlainDateTime(2000, 10, 29, 1, 30);
+
+[
+ [springForwardDatetime, 954671400_000_000_000n],
+ [fallBackDatetime, 972808200_000_000_000n],
+].forEach(([datetime, expected]) => {
+ const explicit = datetime.toZonedDateTime(timeZone, { disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const implicit = datetime.toZonedDateTime(timeZone, {});
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+});
diff --git a/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..6345f97d1d
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/disambiguation-wrong-type.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.tozoneddatetime
+description: Type conversions for disambiguation option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.plaindatetime.prototype.tozoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => datetime.toZonedDateTime(timeZone, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/until/largestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..c5968d7e27
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/until/largestunit-undefined.js b/polyfill/test/PlainDateTime/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..bd3fac403c
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 987, 654, 321, "default largestUnit is day");
diff --git a/polyfill/test/PlainDateTime/prototype/until/largestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..d70e4c3150
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 1, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingincrement-nan.js b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..6ac51771aa
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingincrement-undefined.js b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..14b37755dc
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..474f9e68c5
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaindatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 988, 655, 322);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 397, 1, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingmode-invalid-string.js b/polyfill/test/PlainDateTime/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..37cd149bb6
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingmode-undefined.js b/polyfill/test/PlainDateTime/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..379a007f58
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+
+const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 1, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = earlier.until(later, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainDateTime/prototype/until/roundingmode-wrong-type.js b/polyfill/test/PlainDateTime/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..d2375892a5
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/until/smallestunit-invalid-string.js b/polyfill/test/PlainDateTime/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..0b09706675
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/until/smallestunit-undefined.js b/polyfill/test/PlainDateTime/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..1e1a7245f2
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/PlainDateTime/prototype/until/smallestunit-wrong-type.js b/polyfill/test/PlainDateTime/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..00437a0e41
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/PlainDateTime/prototype/with/overflow-invalid-string.js b/polyfill/test/PlainDateTime/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..f469782e75
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: RangeError thrown when overflow option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.prototype.with step 16:
+ 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" }));
diff --git a/polyfill/test/PlainDateTime/prototype/with/overflow-undefined.js b/polyfill/test/PlainDateTime/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..285c7d04af
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/with/overflow-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Fallback value for overflow option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.prototype.with step 16:
+ 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+const explicit = datetime.with({ minute: 67 }, { overflow: undefined });
+TemporalHelpers.assertPlainDateTime(explicit, 2000, 5, "M05", 2, 12, 59, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = datetime.with({ minute: 67 }, {});
+TemporalHelpers.assertPlainDateTime(implicit, 2000, 5, "M05", 2, 12, 59, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainDateTime/prototype/with/overflow-wrong-type.js b/polyfill/test/PlainDateTime/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..f25e53ed17
--- /dev/null
+++ b/polyfill/test/PlainDateTime/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Type conversions for overflow option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plaindatetime.prototype.with step 16:
+ 16. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12);
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: null }), "null");
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: true }), "true");
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: false }), "false");
+assert.throws(TypeError, () => datetime.with({ minute: 45 }, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateFromFields() in the builtin
+// calendars, to get the option value for the date part, and then once again
+// internally to get the option value for the time part.
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = datetime.with({ minute: 45 }, { overflow: observer });
+TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 12, 45, 0, 0, 0, 0, "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/PlainMonthDay/constructor/from/overflow-invalid-string.js b/polyfill/test/PlainMonthDay/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..108b6c2f0c
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,31 @@
+// 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_).
+---*/
+
+const validValues = [
+ new Temporal.PlainMonthDay(5, 2),
+ { monthCode: "M05", day: 2 },
+ "05-02",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.PlainMonthDay.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/PlainMonthDay/constructor/from/overflow-undefined.js b/polyfill/test/PlainMonthDay/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..f962e7de49
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/constructor/from/overflow-undefined.js
@@ -0,0 +1,40 @@
+// 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]
+---*/
+
+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 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");
diff --git a/polyfill/test/PlainMonthDay/constructor/from/overflow-wrong-type.js b/polyfill/test/PlainMonthDay/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..48e73b5a5b
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,33 @@
+// 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]
+---*/
+
+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),
+));
diff --git a/polyfill/test/PlainMonthDay/prototype/toString/calendarname-invalid-string.js b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..c61b75c326
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-invalid-string.js
@@ -0,0 +1,17 @@
+// 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"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+assert.throws(RangeError, () => monthday.toString({ calendarName: "other string" }));
diff --git a/polyfill/test/PlainMonthDay/prototype/toString/calendarname-undefined.js b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..586138fcae
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,31 @@
+// 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"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const monthday1 = new Temporal.PlainMonthDay(5, 2);
+const monthday2 = new Temporal.PlainMonthDay(5, 2, calendar);
+
+[
+ [monthday1, "05-02"],
+ [monthday2, "1972-05-02[u-ca=custom]"],
+].forEach(([monthday, expected]) => {
+ const explicit = monthday.toString({ calendarName: undefined });
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ const implicit = monthday.toString({});
+ assert.sameValue(implicit, expected, "default calendarName option is auto");
+});
diff --git a/polyfill/test/PlainMonthDay/prototype/toString/calendarname-wrong-type.js b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..8221489bf6
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,25 @@
+// 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"* », *"auto"*).
+ sec-temporal.plainmonthday.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+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),
+);
diff --git a/polyfill/test/PlainMonthDay/prototype/with/overflow-invalid-string.js b/polyfill/test/PlainMonthDay/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..1c5d91438d
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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_).
+---*/
+
+const monthday = new Temporal.PlainMonthDay(5, 2);
+assert.throws(RangeError, () => monthday.with({ day: 8 }, { overflow: "other string" }));
diff --git a/polyfill/test/PlainMonthDay/prototype/with/overflow-undefined.js b/polyfill/test/PlainMonthDay/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..3124b0f842
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/with/overflow-undefined.js
@@ -0,0 +1,23 @@
+// 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]
+---*/
+
+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");
diff --git a/polyfill/test/PlainMonthDay/prototype/with/overflow-wrong-type.js b/polyfill/test/PlainMonthDay/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..1773a42d45
--- /dev/null
+++ b/polyfill/test/PlainMonthDay/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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]
+---*/
+
+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),
+);
diff --git a/polyfill/test/PlainTime/constructor/from/overflow-invalid-string.js b/polyfill/test/PlainTime/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..04bca2a581
--- /dev/null
+++ b/polyfill/test/PlainTime/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,23 @@
+// 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.plaintime.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.plaintime.from step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+---*/
+
+const validValues = [
+ new Temporal.PlainTime(12),
+ { hour: 12 },
+ "12:00",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.PlainTime.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/PlainTime/constructor/from/overflow-undefined.js b/polyfill/test/PlainTime/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..2667cdda40
--- /dev/null
+++ b/polyfill/test/PlainTime/constructor/from/overflow-undefined.js
@@ -0,0 +1,32 @@
+// 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.plaintime.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.plaintime.from step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainTime(12),
+ "12:00",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.PlainTime.from(value, { overflow: undefined });
+ TemporalHelpers.assertPlainTime(explicit, 12, 0, 0, 0, 0, 0, "overflow is ignored");
+ const implicit = Temporal.PlainTime.from(value, {});
+ TemporalHelpers.assertPlainTime(implicit, 12, 0, 0, 0, 0, 0, "overflow is ignored");
+});
+
+const propertyBag = { hour: 26 };
+const explicit = Temporal.PlainTime.from(propertyBag, { overflow: undefined });
+TemporalHelpers.assertPlainTime(explicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = Temporal.PlainTime.from(propertyBag, {});
+TemporalHelpers.assertPlainTime(implicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainTime/constructor/from/overflow-wrong-type.js b/polyfill/test/PlainTime/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..f4bfd28721
--- /dev/null
+++ b/polyfill/test/PlainTime/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,25 @@
+// 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.plaintime.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.plaintime.from step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainTime(12),
+ { hour: 12 },
+ "12:00",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.PlainTime.from(value, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 0, 0, 0, 0, 0, descr),
+));
diff --git a/polyfill/test/PlainTime/prototype/round/roundingincrement-nan.js b/polyfill/test/PlainTime/prototype/round/roundingincrement-nan.js
new file mode 100644
index 0000000000..582be94f69
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingincrement-nan.js
@@ -0,0 +1,17 @@
+// 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.plaintime.prototype.round
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.round step 11:
+ 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+assert.throws(RangeError, () => time.round({ smallestUnit: 'second', roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainTime/prototype/round/roundingincrement-undefined.js b/polyfill/test/PlainTime/prototype/round/roundingincrement-undefined.js
new file mode 100644
index 0000000000..69dd3f73c1
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingincrement-undefined.js
@@ -0,0 +1,23 @@
+// 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.plaintime.prototype.round
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.round step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+
+const explicit = time.round({ smallestUnit: 'second', roundingIncrement: undefined });
+TemporalHelpers.assertPlainTime(explicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
+
+const implicit = time.round({ smallestUnit: 'second' });
+TemporalHelpers.assertPlainTime(implicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainTime/prototype/round/roundingincrement-wrong-type.js b/polyfill/test/PlainTime/prototype/round/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..6af4fd5bf6
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingincrement-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.plaintime.prototype.round
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.round step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => time.round({ smallestUnit: 'second', roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 57, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/round/roundingmode-invalid-string.js b/polyfill/test/PlainTime/prototype/round/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..ea38770b24
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.plaintime.prototype.round
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => time.round({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/round/roundingmode-undefined.js b/polyfill/test/PlainTime/prototype/round/roundingmode-undefined.js
new file mode 100644
index 0000000000..6becf49da8
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.plaintime.prototype.round
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+
+const explicit1 = time.round({ smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertPlainTime(explicit1, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+const implicit1 = time.round({ smallestUnit: "microsecond" });
+TemporalHelpers.assertPlainTime(implicit1, 12, 34, 56, 123, 988, 0, "default roundingMode is halfExpand");
+
+const explicit2 = time.round({ smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertPlainTime(explicit2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+const implicit2 = time.round({ smallestUnit: "millisecond" });
+TemporalHelpers.assertPlainTime(implicit2, 12, 34, 56, 124, 0, 0, "default roundingMode is halfExpand");
+
+const explicit3 = time.round({ smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertPlainTime(explicit3, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
+const implicit3 = time.round({ smallestUnit: "second" });
+TemporalHelpers.assertPlainTime(implicit3, 12, 34, 56, 0, 0, 0, "default roundingMode is halfExpand");
diff --git a/polyfill/test/PlainTime/prototype/round/roundingmode-wrong-type.js b/polyfill/test/PlainTime/prototype/round/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..96536e5dbf
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.plaintime.prototype.round
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand",
+ (roundingMode) => time.round({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/round/smallestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/round/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..b1f9a7e9d0
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.plaintime.prototype.round
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => time.round({ smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/round/smallestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/round/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..e3b4556e24
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/round/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.plaintime.prototype.round
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => time.round({ smallestUnit }),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/since/largestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..a7ba0bf6b8
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/since/largestunit-undefined.js b/polyfill/test/PlainTime/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..862fb2bf7e
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaintime.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour");
diff --git a/polyfill/test/PlainTime/prototype/since/largestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..b8d31ad63e
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "second",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/since/roundingincrement-nan.js b/polyfill/test/PlainTime/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..284dae63ef
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plaintime.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainTime/prototype/since/roundingincrement-undefined.js b/polyfill/test/PlainTime/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..04c92284c7
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainTime/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/PlainTime/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..b84fe539e8
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.since step 11:
+ 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/since/roundingmode-invalid-string.js b/polyfill/test/PlainTime/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..a2f76395b0
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/since/roundingmode-undefined.js b/polyfill/test/PlainTime/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..b6dd3c22ca
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// 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.plaintime.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+
+const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = later.since(earlier, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = later.since(earlier, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = later.since(earlier, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainTime/prototype/since/roundingmode-wrong-type.js b/polyfill/test/PlainTime/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..e2321aedb0
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/since/smallestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..759853af52
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/since/smallestunit-undefined.js b/polyfill/test/PlainTime/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..ce8b47d958
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaintime.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/PlainTime/prototype/since/smallestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..6144c221f5
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js
new file mode 100644
index 0000000000..9179a7da51
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js
@@ -0,0 +1,18 @@
+// 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.plaintime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values
+info: |
+ sec-getstringornumberoption step 4:
+ 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+
+assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-nan.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-nan.js
new file mode 100644
index 0000000000..ac1637bc3d
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-nan.js
@@ -0,0 +1,19 @@
+// 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.plaintime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: NaN }));
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js
new file mode 100644
index 0000000000..780c7040f7
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js
@@ -0,0 +1,19 @@
+// 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.plaintime.prototype.tostring
+description: Rounding for fractionalSecondDigits option
+info: |
+ sec-getstringornumberoption step 3.b:
+ b. Return floor(ℝ(_value_)).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+
+const string = time.toString({ fractionalSecondDigits: 2.5 });
+assert.sameValue(string, "12:34:56.98", "fractionalSecondDigits 2.5 floors to 2");
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js
new file mode 100644
index 0000000000..4ae34e21d5
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js
@@ -0,0 +1,19 @@
+// 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.plaintime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option out of range
+info: |
+ sec-getstringornumberoption step 3.a:
+ a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+
+assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -1 }));
+assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: 10 }));
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-undefined.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-undefined.js
new file mode 100644
index 0000000000..0bbc4ace84
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-undefined.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.tostring
+description: Fallback value for fractionalSecondDigits option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+
+const explicit = time.toString({ fractionalSecondDigits: undefined });
+assert.sameValue(explicit, "12:34:56.98765", "default fractionalSecondDigits is auto");
+
+const implicit = time.toString({});
+assert.sameValue(implicit, "12:34:56.98765", "default fractionalSecondDigits is auto");
diff --git a/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js
new file mode 100644
index 0000000000..865c09b79a
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.tostring
+description: Type conversions for fractionalSecondDigits option
+info: |
+ sec-getoption steps 8–9:
+ 8. Else if _type_ is Number, then
+ a. Set _value_ to ? ToNumber(value).
+ b. ...
+ 9. Else,
+ a. Set _value_ to ? ToString(value).
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.plaintime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0);
+TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(time);
diff --git a/polyfill/test/PlainTime/prototype/toString/roundingmode-invalid-string.js b/polyfill/test/PlainTime/prototype/toString/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..b64689bac1
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.plaintime.prototype.tostring
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => time.toString({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/toString/roundingmode-undefined.js b/polyfill/test/PlainTime/prototype/toString/roundingmode-undefined.js
new file mode 100644
index 0000000000..71f4ecf991
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// 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.plaintime.prototype.tostring
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+
+const explicit1 = time.toString({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1, "12:34:56.123987", "default roundingMode is trunc");
+const implicit1 = time.toString({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1, "12:34:56.123987", "default roundingMode is trunc");
+
+const explicit2 = time.toString({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2, "12:34:56.123", "default roundingMode is trunc");
+const implicit2 = time.toString({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2, "12:34:56.123", "default roundingMode is trunc");
+
+const explicit3 = time.toString({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3, "12:34:56", "default roundingMode is trunc");
+const implicit3 = time.toString({ smallestUnit: "second" });
+assert.sameValue(implicit3, "12:34:56", "default roundingMode is trunc");
diff --git a/polyfill/test/PlainTime/prototype/toString/roundingmode-wrong-type.js b/polyfill/test/PlainTime/prototype/toString/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..23fa311fb7
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.plaintime.prototype.tostring
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => time.toString({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result, "12:34:56.123987", descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/toString/smallestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/toString/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..ac268dbfbf
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// 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.plaintime.prototype.tostring
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+assert.throws(RangeError, () => time.toString({ smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/toString/smallestunit-undefined.js b/polyfill/test/PlainTime/prototype/toString/smallestunit-undefined.js
new file mode 100644
index 0000000000..58c6c91d4c
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/smallestunit-undefined.js
@@ -0,0 +1,20 @@
+// 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.plaintime.prototype.tostring
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+
+const explicit1 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 });
+assert.sameValue(explicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits");
+const implicit1 = time.toString({ fractionalSecondDigits: 6 });
+assert.sameValue(implicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits");
+
+const explicit2 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 });
+assert.sameValue(explicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits");
+const implicit2 = time.toString({ fractionalSecondDigits: 3 });
+assert.sameValue(implicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits");
diff --git a/polyfill/test/PlainTime/prototype/toString/smallestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/toString/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..5d0523c78b
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/toString/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// 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.plaintime.prototype.tostring
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => time.toString({ smallestUnit }),
+ (result, descr) => assert.sameValue(result, "12:34:56.123987", descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/until/largestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..05672e32cc
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/until/largestunit-undefined.js b/polyfill/test/PlainTime/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..043e912122
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaintime.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour");
diff --git a/polyfill/test/PlainTime/prototype/until/largestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..242f1a94f0
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "second",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/until/roundingincrement-nan.js b/polyfill/test/PlainTime/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..ab82a1eb8c
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plaintime.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.until step 10:
+ 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainTime/prototype/until/roundingincrement-undefined.js b/polyfill/test/PlainTime/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..8899a0df46
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.until step 10:
+ 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainTime/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/PlainTime/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..5883c3c24e
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plaintime.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plaintime.prototype.until step 10:
+ 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321);
+const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/until/roundingmode-invalid-string.js b/polyfill/test/PlainTime/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..65f6bb0ced
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/until/roundingmode-undefined.js b/polyfill/test/PlainTime/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..b38133cec2
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// 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.plaintime.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+
+const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 1, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = earlier.until(later, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainTime/prototype/until/roundingmode-wrong-type.js b/polyfill/test/PlainTime/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..4fcfe6acbf
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/until/smallestunit-invalid-string.js b/polyfill/test/PlainTime/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..c0c16e9f5e
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plaintime.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/until/smallestunit-undefined.js b/polyfill/test/PlainTime/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..caff43780c
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plaintime.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/PlainTime/prototype/until/smallestunit-wrong-type.js b/polyfill/test/PlainTime/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..39f2b35619
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plaintime.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0);
+const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/PlainTime/prototype/with/overflow-invalid-string.js b/polyfill/test/PlainTime/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..956e720ffd
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,17 @@
+// 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.plaintime.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.plaintime.prototype.with step 11:
+ 11. Let _overflow_ be ? ToTemporalOverflow(_options_).
+---*/
+
+const time = new Temporal.PlainTime(12);
+assert.throws(RangeError, () => time.with({ minute: 45 }, { overflow: "other string" }));
diff --git a/polyfill/test/PlainTime/prototype/with/overflow-undefined.js b/polyfill/test/PlainTime/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..5f083ce8d0
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/with/overflow-undefined.js
@@ -0,0 +1,21 @@
+// 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.plaintime.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.plaintime.prototype.with step 11:
+ 11. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12);
+const explicit = time.with({ minute: 67 }, { overflow: undefined });
+TemporalHelpers.assertPlainTime(explicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain");
+const implicit = time.with({ minute: 67 }, {});
+TemporalHelpers.assertPlainTime(implicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain");
diff --git a/polyfill/test/PlainTime/prototype/with/overflow-wrong-type.js b/polyfill/test/PlainTime/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..f10014a5a5
--- /dev/null
+++ b/polyfill/test/PlainTime/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,21 @@
+// 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.plaintime.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.plaintime.prototype.with step 11:
+ 11. Let _overflow_ be ? ToTemporalOverflow(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const time = new Temporal.PlainTime(12);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => time.with({ minute: 45 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 45, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/constructor/from/overflow-invalid-string.js b/polyfill/test/PlainYearMonth/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..a80fdfb726
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,31 @@
+// 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.plainyearmonth.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-totemporalyearmonth steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalYearMonth(_item_, _options_).
+---*/
+
+const validValues = [
+ new Temporal.PlainYearMonth(2000, 5),
+ { year: 2000, month: 5 },
+ "2000-05",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.PlainYearMonth.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/PlainYearMonth/constructor/from/overflow-undefined.js b/polyfill/test/PlainYearMonth/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..d3c504e9f1
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/constructor/from/overflow-undefined.js
@@ -0,0 +1,40 @@
+// 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.plainyearmonth.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-totemporalyearmonth steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalYearMonth(_item_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainYearMonth(2000, 5),
+ "2000-05",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.PlainYearMonth.from(value, { overflow: undefined });
+ TemporalHelpers.assertPlainYearMonth(explicit, 2000, 5, "M05", "overflow is ignored");
+ const implicit = Temporal.PlainYearMonth.from(value, {});
+ TemporalHelpers.assertPlainYearMonth(implicit, 2000, 5, "M05", "overflow is ignored");
+});
+
+const propertyBag = { year: 2000, month: 13 };
+const explicit = Temporal.PlainYearMonth.from(propertyBag, { overflow: undefined });
+TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain");
+const implicit = Temporal.PlainYearMonth.from(propertyBag, {});
+TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain");
diff --git a/polyfill/test/PlainYearMonth/constructor/from/overflow-wrong-type.js b/polyfill/test/PlainYearMonth/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..ad4a1a7c2b
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,33 @@
+// 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.plainyearmonth.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-totemporalyearmonth steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ e. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+ 3. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalYearMonth]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ b. Return ...
+ 3. Return ? ToTemporalYearMonth(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.PlainYearMonth(2000, 5),
+ { year: 2000, month: 5 },
+ "2000-05",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.PlainYearMonth.from(value, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr),
+));
diff --git a/polyfill/test/PlainYearMonth/prototype/add/overflow-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/add/overflow-invalid-string.js
new file mode 100644
index 0000000000..6f54e4e800
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/add/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// 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.plainyearmonth.prototype.add
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.add steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/add/overflow-undefined.js b/polyfill/test/PlainYearMonth/prototype/add/overflow-undefined.js
new file mode 100644
index 0000000000..3d1f3712dd
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/add/overflow-undefined.js
@@ -0,0 +1,30 @@
+// 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.plainyearmonth.prototype.add
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.add steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+// In the ISO calendar, PlainYearMonth.prototype.add() actually ignores the
+// overflow option. There is no addition in the ISO calendar that we could test
+// which would actually show a difference between the 'constrain' and 'reject'
+// values.
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+const explicit = yearmonth.add(duration, { overflow: undefined });
+TemporalHelpers.assertPlainYearMonth(explicit, 2001, 6, "M06", "default overflow is constrain");
+const implicit = yearmonth.add(duration, {});
+TemporalHelpers.assertPlainYearMonth(implicit, 2001, 6, "M06", "default overflow is constrain");
diff --git a/polyfill/test/PlainYearMonth/prototype/add/overflow-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/add/overflow-wrong-type.js
new file mode 100644
index 0000000000..bd7bec4509
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/add/overflow-wrong-type.js
@@ -0,0 +1,46 @@
+// 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.plainyearmonth.prototype.add
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.add steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: null }), "null");
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: true }), "true");
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: false }), "false");
+assert.throws(TypeError, () => yearmonth.add(duration, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => yearmonth.add(duration, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateAdd() and then once again by
+// calendar.yearMonthFromFields().
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = yearmonth.add(duration, { overflow: observer });
+TemporalHelpers.assertPlainYearMonth(result, 2001, 6, "M06", "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/PlainYearMonth/prototype/since/largestunit-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..c3d992385b
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/since/largestunit-undefined.js b/polyfill/test/PlainYearMonth/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..a07955aa7e
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plainyearmonth.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year");
diff --git a/polyfill/test/PlainYearMonth/prototype/since/largestunit-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..2f85814fe6
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "month",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-nan.js b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..1887ea004a
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plainyearmonth.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-undefined.js b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..6895612948
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.plainyearmonth.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
+
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..cac7100354
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plainyearmonth.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingmode-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..36c26e513c
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingmode-undefined.js b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..bc35d901eb
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,22 @@
+// 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.plainyearmonth.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 1);
+
+const later1 = new Temporal.PlainYearMonth(2005, 2);
+const explicit1 = later1.since(earlier, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit1 = later1.since(earlier, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+
+const later2 = new Temporal.PlainYearMonth(2005, 12);
+const explicit2 = later2.since(earlier, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit2 = later2.since(earlier, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainYearMonth/prototype/since/roundingmode-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..06f6f26ad3
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "year", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/since/smallestunit-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..951ddf8105
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/since/smallestunit-undefined.js b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..b5a0662282
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plainyearmonth.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month");
diff --git a/polyfill/test/PlainYearMonth/prototype/since/smallestunit-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..234c95829f
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/subtract/overflow-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-invalid-string.js
new file mode 100644
index 0000000000..110f56c460
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// 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.plainyearmonth.prototype.subtract
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.subtract steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/subtract/overflow-undefined.js b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-undefined.js
new file mode 100644
index 0000000000..8710c11259
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-undefined.js
@@ -0,0 +1,30 @@
+// 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.plainyearmonth.prototype.subtract
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.subtract steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+// In the ISO calendar, PlainYearMonth.prototype.subtract() actually ignores the
+// overflow option. There is no subtraction in the ISO calendar that we could
+// test which would actually show a difference between the 'constrain' and
+// 'reject' values.
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+const explicit = yearmonth.subtract(duration, { overflow: undefined });
+TemporalHelpers.assertPlainYearMonth(explicit, 1999, 4, "M04", "default overflow is constrain");
+const implicit = yearmonth.subtract(duration, {});
+TemporalHelpers.assertPlainYearMonth(implicit, 1999, 4, "M04", "default overflow is constrain");
diff --git a/polyfill/test/PlainYearMonth/prototype/subtract/overflow-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-wrong-type.js
new file mode 100644
index 0000000000..451e496b67
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/subtract/overflow-wrong-type.js
@@ -0,0 +1,46 @@
+// 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.plainyearmonth.prototype.subtract
+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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.subtract steps 13–15:
+ 13. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _date_, _durationToAdd_, _options_).
+ 14. ...
+ 15. Return ? YearMonthFromFields(_calendar_, _addedDateFields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const duration = new Temporal.Duration(1, 1);
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: null }), "null");
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: true }), "true");
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: false }), "false");
+assert.throws(TypeError, () => yearmonth.subtract(duration, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateAdd() and then once again by
+// calendar.yearMonthFromFields().
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = yearmonth.subtract(duration, { overflow: observer });
+TemporalHelpers.assertPlainYearMonth(result, 1999, 4, "M04", "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/PlainYearMonth/prototype/toString/calendarname-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..7eb1681e1c
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-invalid-string.js
@@ -0,0 +1,17 @@
+// 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.plainyearmonth.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"* », *"auto"*).
+ sec-temporal.plainyearmonth.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+assert.throws(RangeError, () => yearmonth.toString({ calendarName: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/toString/calendarname-undefined.js b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..bf6d0944a7
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,31 @@
+// 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.plainyearmonth.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"* », *"auto"*).
+ sec-temporal.plainyearmonth.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const yearmonth1 = new Temporal.PlainYearMonth(2000, 5);
+const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar);
+
+[
+ [yearmonth1, "2000-05"],
+ [yearmonth2, "2000-05-01[u-ca=custom]"],
+].forEach(([yearmonth, expected]) => {
+ const explicit = yearmonth.toString({ calendarName: undefined });
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ const implicit = yearmonth.toString({});
+ assert.sameValue(implicit, expected, "default calendarName option is auto");
+});
diff --git a/polyfill/test/PlainYearMonth/prototype/toString/calendarname-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..c1a51ec523
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,25 @@
+// 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.plainyearmonth.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"* », *"auto"*).
+ sec-temporal.plainyearmonth.protoype.tostring step 4:
+ 4. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const yearmonth = new Temporal.PlainYearMonth(2000, 5, calendar);
+
+TemporalHelpers.checkStringOptionWrongType("calendarName", "auto",
+ (calendarName) => yearmonth.toString({ calendarName }),
+ (result, descr) => assert.sameValue(result, "2000-05-01[u-ca=custom]", descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/until/largestunit-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..68829e9d48
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/until/largestunit-undefined.js b/polyfill/test/PlainYearMonth/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..504c720746
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plainyearmonth.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default largestUnit is year");
diff --git a/polyfill/test/PlainYearMonth/prototype/until/largestunit-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..f5c6255972
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "month",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-nan.js b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..813e2b0f75
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// 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.plainyearmonth.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-undefined.js b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..4b8e3e7e97
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// 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.plainyearmonth.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
+
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1");
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..5dd02bd6b1
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// 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.plainyearmonth.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.plainyearmonth.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingmode-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..0e3d6a0f62
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingmode-undefined.js b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..1e7ae8ab71
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,22 @@
+// 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.plainyearmonth.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 1);
+
+const later1 = new Temporal.PlainYearMonth(2005, 2);
+const explicit1 = earlier.until(later1, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later1, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+
+const later2 = new Temporal.PlainYearMonth(2005, 12);
+const explicit2 = earlier.until(later2, { smallestUnit: "year", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later2, { smallestUnit: "year" });
+TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/PlainYearMonth/prototype/until/roundingmode-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..0c7de6eeee
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "year", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/until/smallestunit-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..b95085609c
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// 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.plainyearmonth.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/until/smallestunit-undefined.js b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..30776e0f13
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// 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.plainyearmonth.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "default smallestUnit is month");
diff --git a/polyfill/test/PlainYearMonth/prototype/until/smallestunit-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..860e8dca61
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// 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.plainyearmonth.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.PlainYearMonth(2000, 5);
+const later = new Temporal.PlainYearMonth(2001, 6);
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr),
+);
diff --git a/polyfill/test/PlainYearMonth/prototype/with/overflow-invalid-string.js b/polyfill/test/PlainYearMonth/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..d330d4d6bc
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,19 @@
+// 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.plainyearmonth.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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.with step 16:
+ 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+assert.throws(RangeError, () => yearmonth.with({ month: 8 }, { overflow: "other string" }));
diff --git a/polyfill/test/PlainYearMonth/prototype/with/overflow-undefined.js b/polyfill/test/PlainYearMonth/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..e5f0c68f5f
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/with/overflow-undefined.js
@@ -0,0 +1,23 @@
+// 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.plainyearmonth.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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.with step 16:
+ 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+const explicit = yearmonth.with({ month: 15 }, { overflow: undefined });
+TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain");
+const implicit = yearmonth.with({ month: 15 }, {});
+TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain");
diff --git a/polyfill/test/PlainYearMonth/prototype/with/overflow-wrong-type.js b/polyfill/test/PlainYearMonth/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..8d1356cb4b
--- /dev/null
+++ b/polyfill/test/PlainYearMonth/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,23 @@
+// 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.plainyearmonth.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-isoyearmonthfromfields step 2:
+ 2. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.plainyearmonth.prototype.with step 16:
+ 16. Return ? YearMonthFromFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const yearmonth = new Temporal.PlainYearMonth(2000, 5);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => yearmonth.with({ month: 8 }, { overflow }),
+ (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 8, "M08", descr),
+);
diff --git a/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..be45732da8
--- /dev/null
+++ b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-invalid-string.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getinstantfor
+description: RangeError thrown when disambiguation option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+assert.throws(RangeError, () => timeZone.getInstantFor(datetime, { disambiguation: "other string" }));
diff --git a/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-undefined.js b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-undefined.js
new file mode 100644
index 0000000000..6b133218d7
--- /dev/null
+++ b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-undefined.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getinstantfor
+description: Fallback value for disambiguation option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardDateTime = new Temporal.PlainDateTime(2000, 4, 2, 2, 30);
+const fallBackDateTime = new Temporal.PlainDateTime(2000, 10, 29, 1, 30);
+
+[
+ [springForwardDateTime, 954671400_000_000_000n],
+ [fallBackDateTime, 972808200_000_000_000n],
+].forEach(([datetime, expected]) => {
+ const explicit = timeZone.getInstantFor(datetime, { disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const implicit = timeZone.getInstantFor(datetime, {});
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+});
diff --git a/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..7fbecff038
--- /dev/null
+++ b/polyfill/test/TimeZone/prototype/getInstantFor/disambiguation-wrong-type.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.timezone.prototype.getinstantfor
+description: Type conversions for disambiguation option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.timezone.prototype.getinstantfor step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.PlainDateTime(2001, 9, 9, 1, 46, 40, 987, 654, 321);
+const timeZone = new Temporal.TimeZone("UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => timeZone.getInstantFor(datetime, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/constructor/from/disambiguation-invalid-string.js b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..ac4d829468
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-invalid-string.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: RangeError thrown when disambiguation option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal-totemporalzoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ a. ...
+ b. Perform ? ToTemporalDisambiguation(_options_).
+ c. ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(datetime, { disambiguation: "other string" }));
+
+const timeZone = new Temporal.TimeZone("UTC");
+const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 };
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { disambiguation: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/constructor/from/disambiguation-undefined.js b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-undefined.js
new file mode 100644
index 0000000000..75adbaae0f
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-undefined.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: Fallback value for disambiguation option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal-totemporalzoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardFields = { timeZone, year: 2000, month: 4, day: 2, hour: 2, minute: 30 };
+const fallBackFields = { timeZone, year: 2000, month: 10, day: 29, hour: 1, minute: 30 };
+
+[
+ [springForwardFields, 954671400_000_000_000n],
+ [fallBackFields, 972808200_000_000_000n],
+].forEach(([fields, expected]) => {
+ const explicit = Temporal.ZonedDateTime.from(fields, { disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible (later)");
+
+ // See options-undefined.js for {}
+});
diff --git a/polyfill/test/ZonedDateTime/constructor/from/disambiguation-wrong-type.js b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..4cbcf46e62
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/disambiguation-wrong-type.js
@@ -0,0 +1,35 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: Type conversions for disambiguation option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal-totemporalzoneddatetime step 5:
+ 5. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ a. ...
+ b. Perform ? ToTemporalDisambiguation(_options_).
+ c. ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => Temporal.ZonedDateTime.from(datetime, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
+
+const timeZone = new Temporal.TimeZone("UTC");
+const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 };
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => Temporal.ZonedDateTime.from(propertyBag, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/constructor/from/offset-invalid-string.js b/polyfill/test/ZonedDateTime/constructor/from/offset-invalid-string.js
new file mode 100644
index 0000000000..093aaeb2d1
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/offset-invalid-string.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: RangeError thrown when offset option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal-totemporalzoneddatetime step 6:
+ 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ c. Perform ? ToTemporalOffset(_options_, *"reject"*).
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(datetime, { offset: "other string" }));
+
+const timeZone = new Temporal.TimeZone("UTC");
+const propertyBag = { timeZone, year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 };
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { offset: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/constructor/from/offset-undefined.js b/polyfill/test/ZonedDateTime/constructor/from/offset-undefined.js
new file mode 100644
index 0000000000..95cfd3ea31
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/offset-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: Fallback value for offset option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal-totemporalzoneddatetime step 6:
+ 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ c. Perform ? ToTemporalOffset(_options_, *"reject"*).
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+---*/
+
+const timeZone = new Temporal.TimeZone("-04:00");
+const propertyBag = { timeZone, offset: "+01:00", year: 2020, month: 2, day: 16, hour: 23, minute: 45 };
+
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { offset: undefined }), "default offset is reject");
+// See options-undefined.js for {}
diff --git a/polyfill/test/ZonedDateTime/constructor/from/offset-wrong-type.js b/polyfill/test/ZonedDateTime/constructor/from/offset-wrong-type.js
new file mode 100644
index 0000000000..ddaa48ce9d
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/offset-wrong-type.js
@@ -0,0 +1,34 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.from
+description: Type conversions for offset option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal-totemporalzoneddatetime step 6:
+ 6. Let _offset_ be ? ToTemporalOffset(_options_, *"reject"*).
+ sec-temporal.zoneddatetime.from step 2:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ ...
+ c. Perform ? ToTemporalOffset(_options_, *"reject"*).
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("offset", "reject",
+ (disambiguation) => Temporal.ZonedDateTime.from(datetime, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
+
+const timeZone = new Temporal.TimeZone("UTC");
+const propertyBag = { timeZone, offset: "+00:00", year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, millisecond: 987, microsecond: 654, nanosecond: 321 };
+TemporalHelpers.checkStringOptionWrongType("offset", "reject",
+ (disambiguation) => Temporal.ZonedDateTime.from(propertyBag, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/constructor/from/overflow-invalid-string.js b/polyfill/test/ZonedDateTime/constructor/from/overflow-invalid-string.js
new file mode 100644
index 0000000000..84800e6dd6
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/overflow-invalid-string.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporalzoneddatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+---*/
+
+const validValues = [
+ new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"),
+ { year: 2000, month: 5, day: 2, hour: 12, timeZone: "UTC" },
+ "2001-09-09T01:46:40.987654321+00:00[UTC]",
+];
+validValues.forEach((value) => {
+ assert.throws(RangeError, () => Temporal.ZonedDateTime.from(value, { overflow: "other string" }));
+});
diff --git a/polyfill/test/ZonedDateTime/constructor/from/overflow-undefined.js b/polyfill/test/ZonedDateTime/constructor/from/overflow-undefined.js
new file mode 100644
index 0000000000..b9a1a70b46
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/overflow-undefined.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporalzoneddatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+includes: [temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"),
+ "2001-09-09T01:46:40.987654321+00:00[UTC]",
+];
+validValues.forEach((value) => {
+ const explicit = Temporal.ZonedDateTime.from(value, { overflow: undefined });
+ assert.sameValue(explicit.epochNanoseconds, 1_000_000_000_987_654_321n, "overflow is ignored");
+ const implicit = Temporal.ZonedDateTime.from(value, {});
+ assert.sameValue(implicit.epochNanoseconds, 1_000_000_000_987_654_321n, "overflow is ignored");
+});
+
+const propertyBag = { year: 2000, month: 15, day: 34, hour: 12, timeZone: "UTC" };
+const explicit = Temporal.ZonedDateTime.from(propertyBag, { overflow: undefined });
+assert.sameValue(explicit.epochNanoseconds, 978_264_000_000_000_000n, "default overflow is constrain");
+
+// See options-undefined for {}
diff --git a/polyfill/test/ZonedDateTime/constructor/from/overflow-wrong-type.js b/polyfill/test/ZonedDateTime/constructor/from/overflow-wrong-type.js
new file mode 100644
index 0000000000..862cb257ee
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/constructor/from/overflow-wrong-type.js
@@ -0,0 +1,63 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.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-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-totemporalzoneddatetime steps 2–3:
+ 2. If Type(_item_) is Object, then
+ ...
+ j. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+ 3. Else,
+ a. Perform ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.from steps 2–3:
+ 2. If Type(_item_) is Object and _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
+ a. Perform ? ToTemporalOverflow(_options_).
+ ...
+ d. Return ...
+ 3. Return ? ToTemporalZonedDateTime(_item_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const validValues = [
+ new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"),
+ "2001-09-09T01:46:40.987654321+00:00[UTC]",
+];
+validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => Temporal.ZonedDateTime.from(value, { overflow }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_987_654_321n, descr),
+));
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+const propertyBag = { year: 2001, month: 9, day: 9, hour: 1, minute: 46, second: 40, timeZone: "UTC" };
+
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: null }), "null");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: true }), "true");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: false }), "false");
+assert.throws(TypeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => Temporal.ZonedDateTime.from(propertyBag, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateFromFields() in the builtin
+// calendars, to get the option value for the date part, and then once again
+// internally to get the option value for the time part.
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = Temporal.ZonedDateTime.from(propertyBag, { overflow: observer });
+assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/ZonedDateTime/prototype/add/overflow-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/add/overflow-invalid-string.js
new file mode 100644
index 0000000000..c66032bb90
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/add/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.add step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const duration = new Temporal.Duration(0, 0, 0, 1);
+assert.throws(RangeError, () => datetime.add(duration, { overflow: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/add/overflow-undefined.js b/polyfill/test/ZonedDateTime/prototype/add/overflow-undefined.js
new file mode 100644
index 0000000000..d72d1c498f
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/add/overflow-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.add step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(-1n, "UTC");
+const duration = new Temporal.Duration(0, 2);
+
+const explicit = datetime.add(duration, { overflow: undefined });
+assert.sameValue(explicit.epochNanoseconds, 5097599_999_999_999n, "default overflow is constrain");
+const implicit = datetime.add(duration, {});
+assert.sameValue(implicit.epochNanoseconds, 5097599_999_999_999n, "default overflow is constrain");
diff --git a/polyfill/test/ZonedDateTime/prototype/add/overflow-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/add/overflow-wrong-type.js
new file mode 100644
index 0000000000..b1c03f4249
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/add/overflow-wrong-type.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.add
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.add step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const duration = new Temporal.Duration(0, 0, 0, 1);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => datetime.add(duration, { overflow }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_086_400_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-nan.js b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-nan.js
new file mode 100644
index 0000000000..2cc79eed29
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-nan.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.zoneddatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.round({ smallestUnit: 'second', roundingIncrement: NaN }));
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-undefined.js b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-undefined.js
new file mode 100644
index 0000000000..52fd22fc64
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.zoneddatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+const explicit = datetime.round({ smallestUnit: 'second', roundingIncrement: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1");
+
+const implicit = datetime.round({ smallestUnit: 'second' });
+assert.sameValue(implicit.epochNanoseconds, 1_000_000_001_000_000_000n, "default roundingIncrement is 1");
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..bde6dbadbe
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingincrement-wrong-type.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal-totemporaldatetimeroundingincrement step 5:
+ 5. Return ? ToTemporalRoundingIncrement(_normalizedOptions_, _maximum_, *false*).
+ sec-temporal.zoneddatetime.prototype.round step 8:
+ 8. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_options_, _smallestUnit_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => datetime.round({ smallestUnit: 'second', roundingIncrement }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_001_000_000_000n, descr),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_000_000_000n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingmode-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..dd88d03cb1
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingmode-undefined.js b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-undefined.js
new file mode 100644
index 0000000000..08ba9cb563
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+
+const explicit1 = datetime.round({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand");
+const implicit1 = datetime.round({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1.epochNanoseconds, 1_000_000_000_123_988_000n, "default roundingMode is halfExpand");
+
+const explicit2 = datetime.round({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand");
+const implicit2 = datetime.round({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2.epochNanoseconds, 1_000_000_000_124_000_000n, "default roundingMode is halfExpand");
+
+const explicit3 = datetime.round({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand");
+const implicit3 = datetime.round({ smallestUnit: "second" });
+assert.sameValue(implicit3.epochNanoseconds, 1_000_000_000_000_000_000n, "default roundingMode is halfExpand");
diff --git a/polyfill/test/ZonedDateTime/prototype/round/roundingmode-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..8d3b515244
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand",
+ (roundingMode) => datetime.round({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/round/smallestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/round/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..87ffe6a8e3
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/round/smallestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/round/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..2139b531d5
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/round/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.round
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => datetime.round({ smallestUnit }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_000_000_123_988_000n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/since/largestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/since/largestunit-invalid-string.js
new file mode 100644
index 0000000000..96ef3079b3
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+assert.throws(RangeError, () => later.since(earlier, { largestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/since/largestunit-undefined.js b/polyfill/test/ZonedDateTime/prototype/since/largestunit-undefined.js
new file mode 100644
index 0000000000..42527de0fa
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+
+const explicit = later.since(earlier, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour");
diff --git a/polyfill/test/ZonedDateTime/prototype/since/largestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/since/largestunit-wrong-type.js
new file mode 100644
index 0000000000..8126380c4c
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => later.since(earlier, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-nan.js b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-nan.js
new file mode 100644
index 0000000000..39ecdaec66
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN }));
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-undefined.js b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-undefined.js
new file mode 100644
index 0000000000..de61fd039b
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+
+const explicit = later.since(earlier, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..056a880fd6
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.since step 13:
+ 13. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => later.since(earlier, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingmode-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..b521c58830
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingmode-undefined.js b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-undefined.js
new file mode 100644
index 0000000000..39270d5a2e
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+
+const explicit1 = later.since(earlier, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = later.since(earlier, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = later.since(earlier, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = later.since(earlier, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = later.since(earlier, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = later.since(earlier, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/ZonedDateTime/prototype/since/roundingmode-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..a3d86d9cde
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/since/smallestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..c03df05897
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/since/smallestunit-undefined.js b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-undefined.js
new file mode 100644
index 0000000000..602546cfce
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+
+const explicit = later.since(earlier, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = later.since(earlier, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/ZonedDateTime/prototype/since/smallestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..e733911b59
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/since/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.since
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => later.since(earlier, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/subtract/overflow-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-invalid-string.js
new file mode 100644
index 0000000000..4ce2641bf5
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-invalid-string.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.subtract step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const duration = new Temporal.Duration(0, 0, 0, 1);
+assert.throws(RangeError, () => datetime.subtract(duration, { overflow: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/subtract/overflow-undefined.js b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-undefined.js
new file mode 100644
index 0000000000..b7752b7eb6
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.subtract step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(-1n, "UTC");
+const duration = new Temporal.Duration(0, 1);
+
+const explicit = datetime.subtract(duration, { overflow: undefined });
+assert.sameValue(explicit.epochNanoseconds, -2678400_000_000_001n, "default overflow is constrain");
+const implicit = datetime.subtract(duration, {});
+assert.sameValue(implicit.epochNanoseconds, -2678400_000_000_001n, "default overflow is constrain");
diff --git a/polyfill/test/ZonedDateTime/prototype/subtract/overflow-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-wrong-type.js
new file mode 100644
index 0000000000..4bd7a72b02
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/subtract/overflow-wrong-type.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.subtract
+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.calendar.prototype.dateadd step 7:
+ 7. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal-addzoneddatetime step 6:
+ 6. Let _addedDate_ be ? CalendarDateAdd(_calendar_, _datePart_, _dateDuration_, _options_).
+ sec-temporal.zoneddatetime.prototype.subtract step 7:
+ 7. Let _epochNanoseconds_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _calendar_, −_duration_.[[Years]], −_duration_.[[Months]], −_duration_.[[Weeks]], −_duration_.[[Days]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]], _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const duration = new Temporal.Duration(0, 0, 0, 1);
+TemporalHelpers.checkStringOptionWrongType("overflow", "constrain",
+ (overflow) => datetime.subtract(duration, { overflow }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 999_913_600_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/calendarname-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-invalid-string.js
new file mode 100644
index 0000000000..e17f95e04d
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.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"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ calendarName: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/calendarname-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-undefined.js
new file mode 100644
index 0000000000..17d36b674a
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-undefined.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.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"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const datetime1 = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const datetime2 = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar);
+
+[
+ [datetime1, "2001-09-09T01:46:40.987654321+00:00[UTC]"],
+ [datetime2, "2001-09-09T01:46:40.987654321+00:00[UTC][u-ca=custom]"],
+].forEach(([datetime, expected]) => {
+ const explicit = datetime.toString({ calendarName: undefined });
+ assert.sameValue(explicit, expected, "default calendarName option is auto");
+
+ // See options-undefined.js for {}
+});
+
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/calendarname-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-wrong-type.js
new file mode 100644
index 0000000000..e38551e88a
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/calendarname-wrong-type.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.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"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 6:
+ 6. Let _showCalendar_ be ? ToShowCalendarOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const calendar = {
+ toString() { return "custom"; }
+};
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar);
+
+TemporalHelpers.checkStringOptionWrongType("calendarName", "auto",
+ (calendarName) => datetime.toString({ calendarName }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC][u-ca=custom]", descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
new file mode 100644
index 0000000000..1cf655df58
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values
+info: |
+ sec-getstringornumberoption step 4:
+ 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.instant.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js
new file mode 100644
index 0000000000..26eaec17ac
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-nan.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.zoneddatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: NaN }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js
new file mode 100644
index 0000000000..77399f96b9
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Rounding for fractionalSecondDigits option
+info: |
+ sec-getstringornumberoption step 3.b:
+ b. Return floor(ℝ(_value_)).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.zoneddatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+
+const string = datetime.toString({ fractionalSecondDigits: 2.5 });
+assert.sameValue(string, "2001-09-09T01:46:40.98+00:00[UTC]", "fractionalSecondDigits 2.5 floors to 2");
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
new file mode 100644
index 0000000000..020e9a95e7
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: RangeError thrown when fractionalSecondDigits option out of range
+info: |
+ sec-getstringornumberoption step 3.a:
+ a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.zoneddatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 }));
+assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js
new file mode 100644
index 0000000000..6bdb6ee469
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Fallback value for fractionalSecondDigits option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.zoneddatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+
+const explicit = datetime.toString({ fractionalSecondDigits: undefined });
+assert.sameValue(explicit, "2001-09-09T01:46:40.98765+00:00[UTC]", "default fractionalSecondDigits is auto");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
new file mode 100644
index 0000000000..58887796d1
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Type conversions for fractionalSecondDigits option
+info: |
+ sec-getoption steps 8–9:
+ 8. Else if _type_ is Number, then
+ a. Set _value_ to ? ToNumber(value).
+ b. ...
+ 9. Else,
+ a. Set _value_ to ? ToString(value).
+ sec-getstringornumberoption step 2:
+ 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_).
+ sec-temporal-tosecondsstringprecision step 9:
+ 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*).
+ sec-temporal.zoneddatetime.prototype.tostring step 4:
+ 4. Let _precision_ be ? ToSecondsStringPrecision(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC");
+TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/offset-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/offset-invalid-string.js
new file mode 100644
index 0000000000..012b9dd61c
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/offset-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: RangeError thrown when offset option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-toshowoffsetoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 8:
+ 8. Let _showOffset_ be ? ToShowOffsetOption(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ offset: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/offset-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/offset-undefined.js
new file mode 100644
index 0000000000..2e55202071
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/offset-undefined.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: Fallback value for offset option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-toshowoffsetoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 8:
+ 8. Let _showOffset_ be ? ToShowOffsetOption(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+const explicit = datetime.toString({ offset: undefined });
+assert.sameValue(explicit, "2001-09-09T01:46:40.987654321+00:00[UTC]", "default offset option is auto");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/offset-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/offset-wrong-type.js
new file mode 100644
index 0000000000..c79907644b
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/offset-wrong-type.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: Type conversions for offset option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-toshowoffsetoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 8:
+ 8. Let _showOffset_ be ? ToShowOffsetOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+TemporalHelpers.checkStringOptionWrongType("offset", "auto",
+ (offset) => datetime.toString({ offset }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC]", descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..14b6b10e7b
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-undefined.js
new file mode 100644
index 0000000000..94b9918d15
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-undefined.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+
+const explicit1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: undefined });
+assert.sameValue(explicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default roundingMode is trunc");
+const implicit1 = datetime.toString({ smallestUnit: "microsecond" });
+assert.sameValue(implicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default roundingMode is trunc");
+
+const explicit2 = datetime.toString({ smallestUnit: "millisecond", roundingMode: undefined });
+assert.sameValue(explicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default roundingMode is trunc");
+const implicit2 = datetime.toString({ smallestUnit: "millisecond" });
+assert.sameValue(implicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default roundingMode is trunc");
+
+const explicit3 = datetime.toString({ smallestUnit: "second", roundingMode: undefined });
+assert.sameValue(explicit3, "2001-09-09T01:46:40+00:00[UTC]", "default roundingMode is trunc");
+const implicit3 = datetime.toString({ smallestUnit: "second" });
+assert.sameValue(implicit3, "2001-09-09T01:46:40+00:00[UTC]", "default roundingMode is trunc");
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..360079d43a
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/roundingmode-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => datetime.toString({ smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987+00:00[UTC]", descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..278bac4350
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js
@@ -0,0 +1,10 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-undefined.js
new file mode 100644
index 0000000000..a7a4f69349
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-undefined.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+
+const explicit1 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 });
+assert.sameValue(explicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits");
+const implicit1 = datetime.toString({ fractionalSecondDigits: 6 });
+assert.sameValue(implicit1, "2001-09-09T01:46:40.123987+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits");
+
+const explicit2 = datetime.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 });
+assert.sameValue(explicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits");
+const implicit2 = datetime.toString({ fractionalSecondDigits: 3 });
+assert.sameValue(implicit2, "2001-09-09T01:46:40.123+00:00[UTC]", "default smallestUnit defers to fractionalSecondDigits");
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..a4ecf5615f
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/smallestunit-wrong-type.js
@@ -0,0 +1,14 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.tostring
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => datetime.toString({ smallestUnit }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.123987+00:00[UTC]", descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/timezonename-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-invalid-string.js
new file mode 100644
index 0000000000..bffa1b4f51
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: RangeError thrown when timeZoneName 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-toshowtimezonenameoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 7:
+ 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_64_321n, "UTC");
+assert.throws(RangeError, () => datetime.toString({ timeZoneName: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/timezonename-undefined.js b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-undefined.js
new file mode 100644
index 0000000000..4733eb9244
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-undefined.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: Fallback value for timeZoneName option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-toshowtimezonenameoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 7:
+ 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+const explicit = datetime.toString({ timeZoneName: undefined });
+assert.sameValue(explicit, "2001-09-09T01:46:40.987654321+00:00[UTC]", "default timeZoneName option is auto");
+
+// See options-undefined.js for {}
diff --git a/polyfill/test/ZonedDateTime/prototype/toString/timezonename-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-wrong-type.js
new file mode 100644
index 0000000000..10305853b4
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/toString/timezonename-wrong-type.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.tostring
+description: Type conversions for timeZoneName option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-toshowtimezonenameoption step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*).
+ sec-temporal.zoneddatetime.protoype.tostring step 7:
+ 7. Let _showTimeZone_ be ? ToShowTimeZoneNameOption(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+TemporalHelpers.checkStringOptionWrongType("timeZoneName", "auto",
+ (timeZoneName) => datetime.toString({ timeZoneName }),
+ (result, descr) => assert.sameValue(result, "2001-09-09T01:46:40.987654321+00:00[UTC]", descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/until/largestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/until/largestunit-invalid-string.js
new file mode 100644
index 0000000000..dfd347fc91
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/largestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: RangeError thrown when largestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+assert.throws(RangeError, () => earlier.until(later, { largestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/until/largestunit-undefined.js b/polyfill/test/ZonedDateTime/prototype/until/largestunit-undefined.js
new file mode 100644
index 0000000000..71402099da
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/largestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Fallback value for largestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+
+const explicit = earlier.until(later, { largestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default largestUnit is hour");
diff --git a/polyfill/test/ZonedDateTime/prototype/until/largestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/until/largestunit-wrong-type.js
new file mode 100644
index 0000000000..d20ae85e11
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/largestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Type conversions for largestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("largestUnit", "year",
+ (largestUnit) => earlier.until(later, { largestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 1, 1, 1, 987, 654, 321, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-nan.js b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-nan.js
new file mode 100644
index 0000000000..2f4ac2dead
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-nan.js
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: RangeError thrown when roundingIncrement option is NaN
+info: |
+ sec-getoption step 8.b:
+ b. If _value_ is *NaN*, throw a *RangeError* exception.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN }));
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-undefined.js b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-undefined.js
new file mode 100644
index 0000000000..adcf3effe1
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-undefined.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Fallback value for roundingIncrement option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+
+const explicit = earlier.until(later, { roundingIncrement: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
+
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, "default roundingIncrement is 1");
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js
new file mode 100644
index 0000000000..239f74a13e
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingincrement-wrong-type.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Type conversions for roundingIncrement option
+info: |
+ sec-getoption step 8.a:
+ a. Set _value_ to ? ToNumber(value).
+ sec-temporal-totemporalroundingincrement step 5:
+ 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1).
+ sec-temporal.zoneddatetime.prototype.until step 12:
+ 12. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
+includes: [temporalHelpers.js, compareArray.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_988_655_322n, "UTC");
+
+TemporalHelpers.checkRoundingIncrementOptionWrongType(
+ (roundingIncrement) => earlier.until(later, { roundingIncrement }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 1, descr),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 1, 1, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingmode-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-invalid-string.js
new file mode 100644
index 0000000000..62f46f37e9
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: RangeError thrown when roundingMode option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingmode-undefined.js b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-undefined.js
new file mode 100644
index 0000000000..46a526e3a4
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-undefined.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Fallback value for roundingMode option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+
+const explicit1 = earlier.until(later, { smallestUnit: "microsecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+const implicit1 = earlier.until(later, { smallestUnit: "microsecond" });
+TemporalHelpers.assertDuration(implicit1, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, "default roundingMode is trunc");
+
+const explicit2 = earlier.until(later, { smallestUnit: "millisecond", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+const implicit2 = earlier.until(later, { smallestUnit: "millisecond" });
+TemporalHelpers.assertDuration(implicit2, 0, 0, 0, 0, 25, 1, 1, 123, 0, 0, "default roundingMode is trunc");
+
+const explicit3 = earlier.until(later, { smallestUnit: "second", roundingMode: undefined });
+TemporalHelpers.assertDuration(explicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc");
+const implicit3 = earlier.until(later, { smallestUnit: "second" });
+TemporalHelpers.assertDuration(implicit3, 0, 0, 0, 0, 25, 1, 1, 0, 0, 0, "default roundingMode is trunc");
diff --git a/polyfill/test/ZonedDateTime/prototype/until/roundingmode-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-wrong-type.js
new file mode 100644
index 0000000000..02410549c2
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/roundingmode-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Type conversions for roundingMode option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_123_987_500n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc",
+ (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 123, 987, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/until/smallestunit-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-invalid-string.js
new file mode 100644
index 0000000000..9acde91628
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-invalid-string.js
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: RangeError thrown when smallestUnit option not one of the allowed string values
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/until/smallestunit-undefined.js b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-undefined.js
new file mode 100644
index 0000000000..b6731fd0d2
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-undefined.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Fallback value for smallestUnit option
+includes: [temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+
+const explicit = earlier.until(later, { smallestUnit: undefined });
+TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
+const implicit = earlier.until(later, {});
+TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 25, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond");
diff --git a/polyfill/test/ZonedDateTime/prototype/until/smallestunit-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-wrong-type.js
new file mode 100644
index 0000000000..6fd33fb6dd
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/until/smallestunit-wrong-type.js
@@ -0,0 +1,15 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.until
+description: Type conversions for smallestUnit option
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC");
+const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond",
+ (smallestUnit) => earlier.until(later, { smallestUnit }),
+ (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 25, 1, 1, 987, 654, 0, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/with/disambiguation-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-invalid-string.js
new file mode 100644
index 0000000000..fe56d9d8e7
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.with
+description: RangeError thrown when disambiguation option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.with({ hour: 2 }, { disambiguation: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/with/disambiguation-undefined.js b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-undefined.js
new file mode 100644
index 0000000000..a6eda25dc8
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-undefined.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for disambiguation option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [temporalHelpers.js]
+---*/
+
+const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
+const springForwardDatetime = new Temporal.ZonedDateTime(954702001_000_000_000n, timeZone);
+const fallBackDatetime = new Temporal.ZonedDateTime(972849601_000_000_000n, timeZone);
+const offset = "ignore";
+
+[
+ [springForwardDatetime, { hour: 2, minute: 30 }, 954671401_000_000_000n],
+ [fallBackDatetime, { hour: 1, minute: 30 }, 972808201_000_000_000n],
+].forEach(([datetime, fields, expected]) => {
+ const explicit = datetime.with(fields, { offset, disambiguation: undefined });
+ assert.sameValue(explicit.epochNanoseconds, expected, "default disambiguation is compatible");
+ const implicit = datetime.with(fields, { offset });
+ assert.sameValue(implicit.epochNanoseconds, expected, "default disambiguation is compatible");
+});
diff --git a/polyfill/test/ZonedDateTime/prototype/with/disambiguation-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-wrong-type.js
new file mode 100644
index 0000000000..87fce25273
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/disambiguation-wrong-type.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Type conversions for disambiguation option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaldisambiguation step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ sec-temporal.zoneddatetime.protoype.with step 14:
+ 14. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("disambiguation", "compatible",
+ (disambiguation) => datetime.with({ hour: 2 }, { disambiguation }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/with/offset-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/with/offset-invalid-string.js
new file mode 100644
index 0000000000..4bc3572b6a
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/offset-invalid-string.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.protoype.with
+description: RangeError thrown when offset option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.with({ hour: 2 }, { offset: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/with/offset-undefined.js b/polyfill/test/ZonedDateTime/prototype/with/offset-undefined.js
new file mode 100644
index 0000000000..acb405d61b
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/offset-undefined.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for offset option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+---*/
+
+const timeZone = new Temporal.TimeZone("America/St_Johns");
+
+const datetime = new Temporal.ZonedDateTime(1572757201_000_000_000n, timeZone);
+const explicit = datetime.with({ minute: 31 }, { offset: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer");
+const implicit = datetime.with({ minute: 31 }, {});
+assert.sameValue(implicit.epochNanoseconds, 1572757261_000_000_000n, "default offset is prefer");
diff --git a/polyfill/test/ZonedDateTime/prototype/with/offset-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/with/offset-wrong-type.js
new file mode 100644
index 0000000000..42bf129e5c
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/offset-wrong-type.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Type conversions for offset option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloffset step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ sec-temporal.zoneddatetime.protoype.with step 15:
+ 15. Let _offset_ be ? ToTemporalOffset(_options_, *"prefer"*).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+TemporalHelpers.checkStringOptionWrongType("offset", "prefer",
+ (offset) => datetime.with({ hour: 2 }, { offset }),
+ (result, descr) => assert.sameValue(result.epochNanoseconds, 1_000_003_600_987_654_321n, descr),
+);
diff --git a/polyfill/test/ZonedDateTime/prototype/with/overflow-invalid-string.js b/polyfill/test/ZonedDateTime/prototype/with/overflow-invalid-string.js
new file mode 100644
index 0000000000..c7fe5a053a
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/overflow-invalid-string.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: RangeError thrown when overflow option not one of the allowed string values
+info: |
+ sec-getoption step 10:
+ 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" }));
diff --git a/polyfill/test/ZonedDateTime/prototype/with/overflow-undefined.js b/polyfill/test/ZonedDateTime/prototype/with/overflow-undefined.js
new file mode 100644
index 0000000000..b2deaa566e
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/overflow-undefined.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.zoneddatetime.prototype.with
+description: Fallback value for overflow option
+info: |
+ sec-getoption step 3:
+ 3. If _value_ is *undefined*, return _fallback_.
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+const explicit = datetime.with({ second: 67 }, { overflow: undefined });
+assert.sameValue(explicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain");
+const implicit = datetime.with({ second: 67 }, {});
+assert.sameValue(implicit.epochNanoseconds, 1_000_000_019_987_654_321n, "default overflow is constrain");
diff --git a/polyfill/test/ZonedDateTime/prototype/with/overflow-wrong-type.js b/polyfill/test/ZonedDateTime/prototype/with/overflow-wrong-type.js
new file mode 100644
index 0000000000..d4e5cb5b08
--- /dev/null
+++ b/polyfill/test/ZonedDateTime/prototype/with/overflow-wrong-type.js
@@ -0,0 +1,45 @@
+// Copyright (C) 2021 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-temporal.plaindatetime.prototype.with
+description: Type conversions for overflow option
+info: |
+ sec-getoption step 9.a:
+ a. Set _value_ to ? ToString(_value_).
+ sec-temporal-totemporaloverflow step 1:
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
+ sec-temporal-interprettemporaldatetimefields steps 2–3:
+ 2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
+ 3. Let _overflow_ be ? ToTemporalOverflow(_options_).
+ sec-temporal.zoneddatetime.prototype.with step 24:
+ 24. Let _dateTimeResult_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
+includes: [compareArray.js, temporalHelpers.js]
+---*/
+
+const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC");
+
+// See TemporalHelpers.checkStringOptionWrongType(); this code path has
+// different expectations for observable calls
+
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: null }), "null");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: true }), "true");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: false }), "false");
+assert.throws(TypeError, () => datetime.with({ second: 41 }, { overflow: Symbol() }), "symbol");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: 2n }), "bigint");
+assert.throws(RangeError, () => datetime.with({ second: 41 }, { overflow: {} }), "plain object");
+
+// toString property is read once by Calendar.dateFromFields() in the builtin
+// calendars, to get the option value for the date part, and then once again
+// internally to get the option value for the time part.
+const expected = [
+ "get overflow.toString",
+ "call overflow.toString",
+ "get overflow.toString",
+ "call overflow.toString",
+];
+const actual = [];
+const observer = TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow");
+const result = datetime.with({ second: 41 }, { overflow: observer });
+assert.sameValue(result.epochNanoseconds, 1_000_000_001_987_654_321n, "object with toString");
+assert.compareArray(actual, expected, "order of operations");
diff --git a/polyfill/test/helpers/temporalHelpers.js b/polyfill/test/helpers/temporalHelpers.js
index 37865de1c4..74fb0b88a2 100644
--- a/polyfill/test/helpers/temporalHelpers.js
+++ b/polyfill/test/helpers/temporalHelpers.js
@@ -153,6 +153,39 @@ var TemporalHelpers = {
});
},
+ /*
+ * checkFractionalSecondDigitsOptionWrongType(temporalObject):
+ *
+ * Checks the string-or-number type handling of the fractionalSecondDigits
+ * option to the various types' toString() methods. temporalObject is an
+ * instance of the Temporal type under test.
+ */
+ checkFractionalSecondDigitsOptionWrongType(temporalObject) {
+ // null is not a number, and converts to the string "null", which is an invalid string value
+ assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null");
+ // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid
+ assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true");
+ assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false");
+ // Symbols are not numbers and cannot convert to strings
+ assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol");
+ // BigInts are not numbers and convert to strings which are invalid
+ assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint");
+
+ // Objects are not numbers and prefer their toString() methods when converting to a string
+ assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object");
+
+ const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' });
+ const expected = [
+ "get fractionalSecondDigits.toString",
+ "call fractionalSecondDigits.toString",
+ ];
+ const actual = [];
+ const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits");
+ const result = temporalObject.toString({ fractionalSecondDigits: observer });
+ assert.sameValue(result, toStringExpected, "object with toString");
+ assert.compareArray(actual, expected, "order of operations");
+ },
+
/*
* checkPlainDateTimeConversionFastPath(func):
*
@@ -252,6 +285,81 @@ var TemporalHelpers = {
});
},
+ /*
+ * checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc):
+ *
+ * Checks the type handling of the roundingIncrement option.
+ * checkFunc(roundingIncrement) is a function which takes the value of
+ * roundingIncrement to test, and calls the method under test with it,
+ * returning the result. assertTrueResultFunc(result, description) should
+ * assert that result is the expected result with roundingIncrement: true, and
+ * assertObjectResultFunc(result, description) should assert that result is
+ * the expected result with roundingIncrement being an object with a valueOf()
+ * method.
+ */
+ checkRoundingIncrementOptionWrongType(checkFunc, assertTrueResultFunc, assertObjectResultFunc) {
+ // null converts to 0, which is out of range
+ assert.throws(RangeError, () => checkFunc(null), "null");
+ // Booleans convert to either 0 or 1, and 1 is allowed
+ const trueResult = checkFunc(true);
+ assertTrueResultFunc(trueResult, "true");
+ assert.throws(RangeError, () => checkFunc(false), "false");
+ // Symbols and BigInts cannot convert to numbers
+ assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
+ assert.throws(TypeError, () => checkFunc(2n), "bigint");
+
+ // Objects prefer their valueOf() methods when converting to a number
+ assert.throws(RangeError, () => checkFunc({}), "plain object");
+
+ const expected = [
+ "get roundingIncrement.valueOf",
+ "call roundingIncrement.valueOf",
+ ];
+ const actual = [];
+ const observer = TemporalHelpers.toPrimitiveObserver(actual, 2, "roundingIncrement");
+ const objectResult = checkFunc(observer);
+ assertObjectResultFunc(objectResult, "object with valueOf");
+ assert.compareArray(actual, expected, "order of operations");
+ },
+
+ /*
+ * checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc):
+ *
+ * Checks the type handling of a string option, of which there are several in
+ * Temporal.
+ * propertyName is the name of the option, and value is the value that
+ * assertFunc should expect it to have.
+ * checkFunc(value) is a function which takes the value of the option to test,
+ * and calls the method under test with it, returning the result.
+ * assertFunc(result, description) should assert that result is the expected
+ * result with the option value being an object with a toString() method
+ * which returns the given value.
+ */
+ checkStringOptionWrongType(propertyName, value, checkFunc, assertFunc) {
+ // null converts to the string "null", which is an invalid string value
+ assert.throws(RangeError, () => checkFunc(null), "null");
+ // Booleans convert to the strings "true" or "false", which are invalid
+ assert.throws(RangeError, () => checkFunc(true), "true");
+ assert.throws(RangeError, () => checkFunc(false), "false");
+ // Symbols cannot convert to strings
+ assert.throws(TypeError, () => checkFunc(Symbol()), "symbol");
+ // BigInts convert to strings which are invalid
+ assert.throws(RangeError, () => checkFunc(2n), "bigint");
+
+ // Objects prefer their toString() methods when converting to a string
+ assert.throws(RangeError, () => checkFunc({}), "plain object");
+
+ const expected = [
+ `get ${propertyName}.toString`,
+ `call ${propertyName}.toString`,
+ ];
+ const actual = [];
+ const observer = TemporalHelpers.toPrimitiveObserver(actual, value, propertyName);
+ const result = checkFunc(observer);
+ assertFunc(result, "object with toString");
+ assert.compareArray(actual, expected, "order of operations");
+ },
+
/*
* checkSubclassingIgnored(construct, constructArgs, method, methodArgs,
* resultAssertions):
diff --git a/spec/abstractops.html b/spec/abstractops.html
index 0eed438f19..f96a173c67 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -45,76 +45,51 @@ GetOptionsObject ( _options_ )
-
+
- GetOption ( _options_, _property_, _type_, _values_, _fallback_ )
+ GetOption ( _options_, _property_, _types_, _values_, _fallback_ )
- The abstract operation GetOption extracts the value of the property named _property_ from the provided _options_ object, converts it to the required _type_, checks whether it is one of a List of allowed _values_, and fills in a _fallback_ value if necessary. If _values_ is *undefined*, there is no fixed set of values and any is permitted.
+ The abstract operation GetOption extracts the value of the property named _property_ from the provided _options_ object, checks whether its type is one of a List of allowed _types_ and converts it to the last one if not, checks whether it is one of a List of allowed _values_, and fills in a _fallback_ value if necessary. If _values_ is ~empty~, there is no fixed set of values and any is permitted.
1. Assert: Type(_options_) is Object.
+ 1. Assert: Each element of _types_ is Boolean, String, or Number.
1. Let _value_ be ? Get(_options_, _property_).
1. If _value_ is *undefined*, return _fallback_.
- 1. Assert: _type_ is *"boolean"* or *"string"*.
- 1. If _type_ is *"boolean"*, then
- 1. Let _value_ be ! ToBoolean(_value_).
- 1. If _type_ is *"string"*, then
- 1. Let _value_ be ? ToString(_value_).
- 1. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ 1. If _types_ contains Type(_value_), then
+ 1. Let _type_ be Type(_value_).
+ 1. Else,
+ 1. Let _type_ be the last element of _types_.
+ 1. If _type_ is Boolean, then
+ 1. Set _value_ to ! ToBoolean(_value_).
+ 1. Else if _type_ is Number, then
+ 1. Set _value_ to ? ToNumber(_value_).
+ 1. If _value_ is *NaN*, throw a *RangeError* exception.
+ 1. Else,
+ 1. Set _value_ to ? ToString(_value_).
+ 1. If _values_ is not ~empty~, then
+ 1. If _values_ does not contain _value_, throw a *RangeError* exception.
1. Return _value_.
-
-
- DefaultNumberOption ( _value_, _minimum_, _maximum_, _fallback_ )
-
-
- The abstract operation DefaultNumberOption converts _value_ to a Number value, checks whether it is in the allowed range, and fills in a _fallback_ value if necessary.
-
-
-
- 1. If _value_ is *undefined*, return _fallback_.
- 1. Let _value_ be ? ToNumber(_value_).
- 1. If _value_ is *NaN* or less than _minimum_ or greater than _maximum_, throw a *RangeError* exception.
- 1. Return floor(_value_).
-
-
-
-
-
- GetNumberOption ( _options_, _property_, _minimum_, _maximum_, _fallback_ )
-
-
- The abstract operation GetNumberOption extracts the value of the property named _property_ from the provided _options_ object, converts it to a Number value, checks whether it is in the allowed range, and fills in a _fallback_ value if necessary.
-
-
-
- 1. Assert: Type(_options_) is Object.
- 1. Let _value_ be ? Get(_options_, _property_).
- 1. Return ? DefaultNumberOption(_value_, _minimum_, _maximum_, _fallback_).
-
-
-
GetStringOrNumberOption ( _options_, _property_, _stringValues_, _minimum_, _maximum_, _fallback_ )
The abstract operation GetStringOrNumberOption extracts the value of the property named _property_ from the provided _options_ object.
If the value is a Number value, the operation checks whether it is in the allowed range.
Otherwise, the operation converts it to a string and checks whether it is one of a List of allowed _stringValues_, and fills in a _fallback_ value if necessary.
- If _stringValues_ is *undefined*, there is no fixed set of values and any is permitted.
1. Assert: Type(_options_) is Object.
- 1. Let _value_ be ? Get(_options_, _property_).
- 1. If _value_ is *undefined*, return _fallback_.
+ 1. Let _value_ be ? GetOption(_options_, _property_, « Number, String », ~empty~, _fallback_).
1. If Type(_value_) is Number, then
- 1. If _value_ is *NaN*, or _value_ < _minimum_, or _value_ > _maximum_, throw a *RangeError* exception.
+ 1. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception.
1. Return floor(ℝ(_value_)).
- 1. Set _value_ to ? ToString(_value_).
- 1. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception.
+ 1. Assert: Type(_value_) is String.
+ 1. If _stringValues_ does not contain _value_, throw a *RangeError* exception.
1. Return _value_.
@@ -159,14 +134,14 @@ DurationHandleFractions ( _fHours_, _minutes_, _fMinutes_, _seconds_, _fSeco
ToTemporalOverflow ( _normalizedOptions_ )
- 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, *"string"*, « *"constrain"*, *"reject"* », *"constrain"*).
+ 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*).
ToTemporalDisambiguation ( _normalizedOptions_ )
- 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, *"string"*, « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
+ 1. Return ? GetOption(_normalizedOptions_, *"disambiguation"*, « String », « *"compatible"*, *"earlier"*, *"later"*, *"reject"* », *"compatible"*).
@@ -182,7 +157,7 @@ ToTemporalRoundingMode ( _normalizedOptions_, _fallback_ )
- 1. Return ? GetOption(_normalizedOptions_, *"roundingMode"*, *"string"*, « *"ceil"*, *"floor"*, *"trunc"*, *"halfExpand"* », _fallback_).
+ 1. Return ? GetOption(_normalizedOptions_, *"roundingMode"*, « String », « *"ceil"*, *"floor"*, *"trunc"*, *"halfExpand"* », _fallback_).
@@ -210,7 +185,7 @@ ToTemporalOffset ( _normalizedOptions_, _fallback_ )
The value _fallback_ is returned if the property is not present.
- 1. Return ? GetOption(_normalizedOptions_, *"offset"*, *"string"*, « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"prefer"*, *"use"*, *"ignore"*, *"reject"* », _fallback_).
@@ -223,7 +198,7 @@ ToShowCalendarOption ( _normalizedOptions_ )
This property is used in `toString` methods in Temporal to control whether a calendar annotation should be output.
- 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, *"string"*, « *"auto"*, *"always"*, *"never"* », *"auto"*).
+ 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, « String », « *"auto"*, *"always"*, *"never"* », *"auto"*).
@@ -237,7 +212,7 @@ ToShowTimeZoneNameOption ( _normalizedOptions_ )
It is different from the `timeZone` property passed to `Temporal.ZonedDateTime.from()` and from the `timeZone` property in the options passed to `Temporal.Instant.prototype.toString()`.
- 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, *"string"*, « *"auto"*, *"never"* », *"auto"*).
+ 1. Return ? GetOption(_normalizedOptions_, *"timeZoneName"*, « String », « *"auto"*, *"never"* », *"auto"*).
@@ -251,7 +226,7 @@ ToShowOffsetOption ( _normalizedOptions_ )
It is different from the `offset` property passed to `Temporal.ZonedDateTime.from()`.
- 1. Return ? GetOption(_normalizedOptions_, *"offset"*, *"string"*, « *"auto"*, *"never"* », *"auto"*).
+ 1. Return ? GetOption(_normalizedOptions_, *"offset"*, « String », « *"auto"*, *"never"* », *"auto"*).
@@ -266,7 +241,9 @@ ToTemporalRoundingIncrement ( _normalizedOptions_, _dividend_, _inclusive_ )
1. Let _maximum_ be _dividend_ − 1.
1. Else,
1. Let _maximum_ be 1.
- 1. Let _increment_ be ? GetNumberOption(_normalizedOptions_, *"roundingIncrement"*, 1, _maximum_, 1).
+ 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », ~empty~, 1).
+ 1. If _increment_ < 1 or _increment_ > _maximum_, throw a *RangeError* exception.
+ 1. Set _increment_ to floor(ℝ(_increment_)).
1. If _dividend_ is not *undefined* and _dividend_ modulo _increment_ is not zero, then
1. Throw a *RangeError* exception.
1. Return _increment_.
@@ -378,7 +355,7 @@ ToLargestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_ [
1. Assert: _disallowedUnits_ does not contain _fallback_ or *"auto"*.
1. Assert: If _autoValue_ is present, _fallback_ is *"auto"*, and _disallowedUnits_ does not contain _autoValue_.
- 1. Let _largestUnit_ be ? GetOption(_normalizedOptions_, *"largestUnit"*, *"string"*, « *"auto"*, *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
+ 1. Let _largestUnit_ be ? GetOption(_normalizedOptions_, *"largestUnit"*, « String », « *"auto"*, *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
1. If _largestUnit_ is *"auto"* and _autoValue_ is present, then
1. Return _autoValue_.
1. If the value of _largestUnit_ is in the Plural column of , then
@@ -400,7 +377,7 @@ ToSmallestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_
1. Assert: _disallowedUnits_ does not contain _fallback_.
- 1. Let _smallestUnit_ be ? GetOption(_normalizedOptions_, *"smallestUnit"*, *"string"*, « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
+ 1. Let _smallestUnit_ be ? GetOption(_normalizedOptions_, *"smallestUnit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_).
1. If the value of _smallestUnit_ is in the Plural column of , then
1. Set _smallestUnit_ to the corresponding Singular value of the same row.
1. If _disallowedUnits_ contains _smallestUnit_, then
@@ -419,7 +396,7 @@ ToTemporalDurationTotalUnit ( _normalizedOptions_ )
Both singular and plural unit names are accepted, but only the singular form is returned.
- 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, *"string"*, « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*).
+ 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*).
1. If the value of _unit_ is in the Plural column of , then
1. Set _unit_ to the corresponding Singular value of the same row.
1. Return _unit_.
diff --git a/spec/intl.html b/spec/intl.html
index 3a271a22ea..41e8d6fc12 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -106,58 +106,6 @@
-
-
-
- GetOption ( _options_, _property_, _type_, _values_, _fallback_ )
-
-
- The abstract operation GetOption extracts the value of the property named _property_ from the provided _options_ object, converts it to the required _type_, checks whether it is one of a List of allowed _values_, and fills in a _fallback_ value if necessary. If _values_ is *undefined*, there is no fixed set of values and any is permitted.
-
-
-
- 1. Assert: Type(_options_) is Object.
- 1. Let _value_ be ? Get(_options_, _property_).
- 1. If _value_ is *undefined*, return _fallback_.
- 1. Assert: _type_ is *"boolean"* or *"string"*.
- 1. If _type_ is *"boolean"*, then
- 1. Let _value_ be ! ToBoolean(_value_).
- 1. If _type_ is *"string"*, then
- 1. Let _value_ be ? ToString(_value_).
- 1. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception.
- 1. Return _value_.
-
-
-
-
- DefaultNumberOption ( _value_, _minimum_, _maximum_, _fallback_ )
-
-
- The abstract operation DefaultNumberOption converts _value_ to a Number value, checks whether it is in the allowed range, and fills in a _fallback_ value if necessary.
-
-
-
- 1. If _value_ is *undefined*, return _fallback_.
- 1. Let _value_ be ? ToNumber(_value_).
- 1. If _value_ is *NaN* or less than _minimum_ or greater than _maximum_, throw a *RangeError* exception.
- 1. Return floor(_value_).
-
-
-
-
- GetNumberOption ( _options_, _property_, _minimum_, _maximum_, _fallback_ )
-
-
- The abstract operation GetNumberOption extracts the value of the property named _property_ from the provided _options_ object, converts it to a Number value, checks whether it is in the allowed range, and fills in a _fallback_ value if necessary.
-
-
-
- 1. Assert: Type(_options_) is Object.
- 1. Let _value_ be ? Get(_options_, _property_).
- 1. Return ? DefaultNumberOption(_value_, _minimum_, _maximum_, _fallback_).
-
-
-