diff --git a/features.txt b/features.txt index 367e8d9d4c6..e85ecc3f188 100644 --- a/features.txt +++ b/features.txt @@ -260,6 +260,10 @@ ShadowRealm # https://github.com/tc39/proposal-array-find-from-last array-find-from-last +# Array.prototype.groupBy & Array.prototype.groupByToMap +# https://github.com/tc39/proposal-array-grouping +array-grouping + # Intl.DurationFormat # https://github.com/tc39/proposal-intl-duration-format Intl.DurationFormat diff --git a/test/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js b/test/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js new file mode 100644 index 00000000000..ba304c4ca3b --- /dev/null +++ b/test/built-ins/Array/prototype/Symbol.unscopables/array-find-from-last.js @@ -0,0 +1,31 @@ +// Copyright (C) 2022 Microsoft. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype-@@unscopables +description: > + Initial value of `Symbol.unscopables` property +info: | + 22.1.3.32 Array.prototype [ @@unscopables ] + + ... + 7. Perform CreateDataProperty(unscopableList, "findLast", true). + 8. Perform CreateDataProperty(unscopableList, "findLastIndex", true). + ... + +includes: [propertyHelper.js] +features: [Symbol.unscopables, array-find-from-last] +---*/ + +var unscopables = Array.prototype[Symbol.unscopables]; + +assert.sameValue(Object.getPrototypeOf(unscopables), null); + +assert.sameValue(unscopables.findLast, true, '`findLast` property value'); +verifyEnumerable(unscopables, 'findLast'); +verifyWritable(unscopables, 'findLast'); +verifyConfigurable(unscopables, 'findLast'); + +assert.sameValue(unscopables.findLastIndex, true, '`findLastIndex` property value'); +verifyEnumerable(unscopables, 'findLastIndex'); +verifyWritable(unscopables, 'findLastIndex'); +verifyConfigurable(unscopables, 'findLastIndex'); diff --git a/test/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js b/test/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js new file mode 100644 index 00000000000..4e58eb711aa --- /dev/null +++ b/test/built-ins/Array/prototype/Symbol.unscopables/array-grouping.js @@ -0,0 +1,31 @@ +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-array.prototype-@@unscopables +description: > + Initial value of `Symbol.unscopables` property +info: | + 22.1.3.32 Array.prototype [ @@unscopables ] + + ... + 10. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupBy", true). + 11. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupByToMap", true). + ... + +includes: [propertyHelper.js] +features: [Symbol.unscopables, array-grouping] +---*/ + +var unscopables = Array.prototype[Symbol.unscopables]; + +assert.sameValue(Object.getPrototypeOf(unscopables), null); + +assert.sameValue(unscopables.groupBy, true, '`groupBy` property value'); +verifyEnumerable(unscopables, 'groupBy'); +verifyWritable(unscopables, 'groupBy'); +verifyConfigurable(unscopables, 'groupBy'); + +assert.sameValue(unscopables.groupByToMap, true, '`groupByToMap` property value'); +verifyEnumerable(unscopables, 'groupByToMap'); +verifyWritable(unscopables, 'groupByToMap'); +verifyConfigurable(unscopables, 'groupByToMap'); diff --git a/test/built-ins/Array/prototype/Symbol.unscopables/value.js b/test/built-ins/Array/prototype/Symbol.unscopables/value.js index 526cf8b877a..a3c4f5fd1a1 100644 --- a/test/built-ins/Array/prototype/Symbol.unscopables/value.js +++ b/test/built-ins/Array/prototype/Symbol.unscopables/value.js @@ -13,19 +13,16 @@ info: | 4. Perform CreateDataProperty(unscopableList, "fill", true). 5. Perform CreateDataProperty(unscopableList, "find", true). 6. Perform CreateDataProperty(unscopableList, "findIndex", true). - 7. Perform CreateDataProperty(unscopableList, "findLast", true). - 8. Perform CreateDataProperty(unscopableList, "findLastIndex", true). - 9. Perform CreateDataProperty(unscopableList, "flat", true). - 10. Perform CreateDataProperty(unscopableList, "flatMap", true). - 11. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupBy", true). - 12. Perform ! CreateDataPropertyOrThrow(unscopableList, "groupByToMap", true). - 13. Perform CreateDataProperty(unscopableList, "includes", true). - 14. Perform CreateDataProperty(unscopableList, "keys", true). - 15. Perform CreateDataProperty(unscopableList, "values", true). - 16. Assert: Each of the above calls returns true. - 17. Return unscopableList. + 7. Perform CreateDataProperty(unscopableList, "flat", true). + 8. Perform CreateDataProperty(unscopableList, "flatMap", true). + 9. Perform CreateDataProperty(unscopableList, "includes", true). + 10. Perform CreateDataProperty(unscopableList, "keys", true). + 11. Perform CreateDataProperty(unscopableList, "values", true). + 12. Assert: Each of the above calls returns true. + 13. Return unscopableList. + includes: [propertyHelper.js] -features: [Symbol.unscopables, array-find-from-last] +features: [Symbol.unscopables] ---*/ var unscopables = Array.prototype[Symbol.unscopables]; @@ -57,17 +54,6 @@ verifyEnumerable(unscopables, 'findIndex'); verifyWritable(unscopables, 'findIndex'); verifyConfigurable(unscopables, 'findIndex'); - -assert.sameValue(unscopables.findLast, true, '`findLast` property value'); -verifyEnumerable(unscopables, 'findLast'); -verifyWritable(unscopables, 'findLast'); -verifyConfigurable(unscopables, 'findLast'); - -assert.sameValue(unscopables.findLastIndex, true, '`findLastIndex` property value'); -verifyEnumerable(unscopables, 'findLastIndex'); -verifyWritable(unscopables, 'findLastIndex'); -verifyConfigurable(unscopables, 'findLastIndex'); - assert.sameValue(unscopables.flat, true, '`flat` property value'); verifyEnumerable(unscopables, 'flat'); verifyWritable(unscopables, 'flat'); @@ -78,16 +64,6 @@ verifyEnumerable(unscopables, 'flatMap'); verifyWritable(unscopables, 'flatMap'); verifyConfigurable(unscopables, 'flatMap'); -assert.sameValue(unscopables.groupBy, true, '`groupBy` property value'); -verifyEnumerable(unscopables, 'groupBy'); -verifyWritable(unscopables, 'groupBy'); -verifyConfigurable(unscopables, 'groupBy'); - -assert.sameValue(unscopables.groupByToMap, true, '`groupByToMap` property value'); -verifyEnumerable(unscopables, 'groupByToMap'); -verifyWritable(unscopables, 'groupByToMap'); -verifyConfigurable(unscopables, 'groupByToMap'); - assert.sameValue(unscopables.includes, true, '`includes` property value'); verifyEnumerable(unscopables, 'includes'); verifyWritable(unscopables, 'includes'); diff --git a/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js b/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js new file mode 100644 index 00000000000..ee964823a24 --- /dev/null +++ b/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js @@ -0,0 +1,40 @@ +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist +description: > + WrappedFunctionCreate throws a TypeError the target is a revoked proxy. + +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + 1. Let target be F.[[WrappedTargetFunction]]. + 2. Assert: IsCallable(target) is true. + 3. Let callerRealm be F.[[Realm]]. + 4. NOTE: Any exception objects produced after this point are associated with callerRealm. + 5. Let targetRealm be ? GetFunctionRealm(target). + ... + + GetFunctionRealm ( obj ) + ... + 3. If obj is a Proxy exotic object, then + a. If obj.[[ProxyHandler]] is null, throw a TypeError exception. + ... + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +const fn = r.evaluate(` +globalThis.revocable = Proxy.revocable(() => {}, {}); + +globalThis.revocable.proxy; +`); +r.evaluate('revocable.revoke()'); +assert.throws(TypeError, () => fn()); diff --git a/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js b/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js new file mode 100644 index 00000000000..b3cec5b115e --- /dev/null +++ b/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js @@ -0,0 +1,70 @@ +// Copyright (C) 2022 Chengzhong Wu. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-wrappedfunctioncreate +description: > + WrappedFunctionCreate throws a TypeError if the accessing target's property may throw. + +info: | + WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) + ... + 7. Let result be CopyNameAndLength(wrapped, Target). + ... + + CopyNameAndLength ( F: a function object, Target: a function object, optional prefix: a String, optional argCount: a Number, ) + ... + 3. Let targetHasLength be ? HasOwnProperty(Target, "length"). + 4. If targetHasLength is true, then + a. Let targetLen be ? Get(Target, "length"). + ... + 6. Let targetName be ? Get(Target, "name"). + +features: [ShadowRealm] +---*/ + +assert.sameValue( + typeof ShadowRealm.prototype.evaluate, + 'function', + 'This test must fail if ShadowRealm.prototype.evaluate is not a function' +); + +const r = new ShadowRealm(); + +assert.throws(TypeError, () => r.evaluate(` +const revocable = Proxy.revocable(() => {}, {}); +revocable.revoke(); + +revocable.proxy; +`), 'TypeError on wrapping a revoked callable proxy'); + +assert.throws(TypeError, () => r.evaluate(` +const fn = () => {}; +Object.defineProperty(fn, 'name', { + get() { + throw new Error(); + }, +}); + +fn; +`), 'TypeError on wrapping a fn with throwing name accessor'); + +assert.throws(TypeError, () => r.evaluate(` +const fn = () => {}; +Object.defineProperty(fn, 'length', { + get() { + throw new Error(); + }, +}); + +fn; +`), 'TypeError on wrapping a fn with throwing length accessor'); + +assert.throws(TypeError, () => r.evaluate(` +const proxy = new Proxy(() => {}, { + getOwnPropertyDescriptor(target, key) { + throw new Error(); + }, +}); + +proxy; +`), 'TypeError on wrapping a callable proxy with throwing getOwnPropertyDescriptor trap'); diff --git a/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js b/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js index 06d9453fa10..55fd38f54b0 100644 --- a/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js +++ b/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js @@ -1,15 +1,21 @@ // Copyright 2012 Norbert Lindenberg. All rights reserved. // Copyright 2012 Mozilla Corporation. All rights reserved. // Copyright 2013 Microsoft Corporation. All rights reserved. +// Copyright (C) 2022 Richard Gibson. All rights reserved. // This code is governed by the license found in the LICENSE file. /*--- -es5id: 15.5.4.9_CE description: > - Tests that String.prototype.localeCompare returns 0 when - comparing Strings that are considered canonically equivalent by - the Unicode standard. -author: Norbert Lindenberg + String.prototype.localeCompare must return 0 when + comparing Strings that are considered canonically equivalent by + the Unicode Standard. +esid: sec-string.prototype.localecompare +info: | + String.prototype.localeCompare ( _that_ [ , _reserved1_ [ , _reserved2_ ] ] ) + + This function must treat Strings that are canonically equivalent + according to the Unicode standard as identical and must return `0` + when comparing Strings that are considered canonically equivalent. ---*/ // pairs with characters not in Unicode 3.0 are commented out @@ -49,26 +55,12 @@ var pairs = [ // ["\uD87E\uDC2B", "北"] ]; -// Detect whether we are using locale-sensitive comparisons or a bitwise comparison -if ("a".localeCompare("Z") < 0) { - // We are using locale-sensitive comparison, so all pairs should be canonically equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) !== 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); - } - } -} else { - // We are using bitwise comparison, so all pairs should not be equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) === 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") = " + pair[1] + " (" + toU(pair[1]) + ")."); - } +var i; +for (i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + if (pair[0].localeCompare(pair[1]) !== 0) { + throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + + ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); } } diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js new file mode 100644 index 00000000000..834d82a7ebb --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateAdd(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js index 3197c54007c..df173c933f7 100644 --- a/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js @@ -17,6 +17,11 @@ features: [Temporal, arrow-function] 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" }), - "Value for overflow not one of the allowed string values"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateAdd(date, duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js index 6cc0d01724d..28e81de7ceb 100644 --- a/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal, arrow-function] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, - { overflow: "other string" }), - "Value for overflow not one of the allowed string values"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, + { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js new file mode 100644 index 00000000000..a3ecc5814d1 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js @@ -0,0 +1,67 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2020, 1, 1, instance); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateUntil(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js new file mode 100644 index 00000000000..95a33903b79 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.day(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js new file mode 100644 index 00000000000..77d600bffde --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js new file mode 100644 index 00000000000..8768faa6381 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js new file mode 100644 index 00000000000..97ecac0fa8f --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js new file mode 100644 index 00000000000..9c98bd32957 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js new file mode 100644 index 00000000000..8d92ef970d0 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js new file mode 100644 index 00000000000..6a1c1d5d6b7 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js new file mode 100644 index 00000000000..e314a1d01e3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.month(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js new file mode 100644 index 00000000000..3994dee3bc9 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js index 2e87dc1a67a..6844c7e3d2b 100644 --- a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js @@ -17,4 +17,11 @@ features: [Temporal] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js new file mode 100644 index 00000000000..811a6e00cb3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js new file mode 100644 index 00000000000..7b8e721b7e3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js new file mode 100644 index 00000000000..e186a2321f8 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.year(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js new file mode 100644 index 00000000000..2624bc7b651 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +let result = cal.yearMonthFromFields({ year: 2021, month: 7 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, month 7"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, month 12"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, monthCode M07"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, monthCode M12"); + +["constrain", "reject"].forEach((overflow) => { + const opt = { overflow }; + result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, month 7, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, month 12, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, monthCode M07, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, monthCode M12, overflow ${overflow}`); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js index 0839394ca96..7212b7f1d6c 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js @@ -11,12 +11,14 @@ const yearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; assert.sameValue(typeof yearMonthFromFields, "function"); -assert.throws(TypeError, () => yearMonthFromFields.call(undefined), "undefined"); -assert.throws(TypeError, () => yearMonthFromFields.call(null), "null"); -assert.throws(TypeError, () => yearMonthFromFields.call(true), "true"); -assert.throws(TypeError, () => yearMonthFromFields.call(""), "empty string"); -assert.throws(TypeError, () => yearMonthFromFields.call(Symbol()), "symbol"); -assert.throws(TypeError, () => yearMonthFromFields.call(1), "1"); -assert.throws(TypeError, () => yearMonthFromFields.call({}), "plain object"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = { year: 2021, month: 1 }; + +assert.throws(TypeError, () => yearMonthFromFields.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => yearMonthFromFields.call(null, arg), "null"); +assert.throws(TypeError, () => yearMonthFromFields.call(true, arg), "true"); +assert.throws(TypeError, () => yearMonthFromFields.call("", arg), "empty string"); +assert.throws(TypeError, () => yearMonthFromFields.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => yearMonthFromFields.call(1, arg), "1"); +assert.throws(TypeError, () => yearMonthFromFields.call({}, arg), "plain object"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js new file mode 100644 index 00000000000..c63d8f39e6c --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.yearMonthFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ month: 1 }), "year is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ year: 2021 }), "month or monthCode is required"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js index 7969ba6e441..e04972b2dde 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js @@ -7,7 +7,7 @@ description: Throw a TypeError if the fields is not an object features: [Symbol, Temporal] ---*/ -const tests = [undefined, null, false, "string", Symbol("sym"), Math.PI, 42n]; +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; const iso = Temporal.Calendar.from("iso8601"); for (const fields of tests) { assert.throws(TypeError, () => iso.yearMonthFromFields(fields, {})); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js new file mode 100644 index 00000000000..0b01bf85a75 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, month: 12, monthCode: "M11" }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not valid for year 2021`); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js new file mode 100644 index 00000000000..0246e70bbcc --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js @@ -0,0 +1,17 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if options is not an object or undefined +info: | + 5. Set options to ? GetOptionsObject(options). +features: [Symbol, Temporal] +---*/ + +const tests = [null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = new Temporal.Calendar("iso8601"); +for (const options of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields({ year: 2021, month: 7 }, options), + "options is not object"); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js new file mode 100644 index 00000000000..6384d42a285 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js @@ -0,0 +1,91 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") +const opt = { overflow: "constrain" }; + +let result = cal.yearMonthFromFields({ year: 2021, month: 1 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "month 1 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 2 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "month 2 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 3 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "month 3 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 4 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "month 4 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 5 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "month 5 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 6 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "month 6 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "month 7 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 8 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "month 8 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 9 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "month 9 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 10 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "month 10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 11 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "month 11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 12 with overflow constrain"); + +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -99999 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: 0 }, opt), + "month zero is out of range even with overflow constrain" +) + +result = cal.yearMonthFromFields({ year: 2021, month: 13 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 13 is constrained to 12"); +result = cal.yearMonthFromFields({ year: 2021, month: 99999 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 99999 is constrained to 12"); + +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M01" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "monthCode M01 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M02" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "monthCode M02 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M03" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "monthCode M03 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M04" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "monthCode M04 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M05" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "monthCode M05 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M06" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "monthCode M06 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "monthCode M07 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M08" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "monthCode M08 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M09" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "monthCode M09 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M10" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "monthCode M10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M11" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "monthCode M11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "monthCode M12 with overflow constrain"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js index 99ffe6af277..77c14141097 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js @@ -17,4 +17,11 @@ features: [Temporal] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js new file mode 100644 index 00000000000..d0d475d9e7b --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js @@ -0,0 +1,26 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.yearMonthFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); diff --git a/test/built-ins/Temporal/Duration/basic.js b/test/built-ins/Temporal/Duration/basic.js new file mode 100644 index 00000000000..69cea7447c2 --- /dev/null +++ b/test/built-ins/Temporal/Duration/basic.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Basic constructor tests. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertDuration(new Temporal.Duration(5, 5, 5, 5, 5, 5, 5, 5, 5, 0), + 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, "positive"); +TemporalHelpers.assertDuration(new Temporal.Duration(-5, -5, -5, -5, -5, -5, -5, -5, -5, 0), + -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, "negative"); +TemporalHelpers.assertDuration(new Temporal.Duration(-0, -0, -0, -0, -0, -0, -0, -0, -0, -0), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "negative zero"); diff --git a/test/built-ins/Temporal/Duration/call-builtin.js b/test/built-ins/Temporal/Duration/call-builtin.js new file mode 100644 index 00000000000..1050ec96729 --- /dev/null +++ b/test/built-ins/Temporal/Duration/call-builtin.js @@ -0,0 +1,15 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Constructor should not call built-in functions. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +Number.isFinite = () => { throw new Test262Error("should not call Number.isFinite") }; +Math.sign = () => { throw new Test262Error("should not call Math.sign") }; + +const duration = new Temporal.Duration(1, 1); +TemporalHelpers.assertDuration(duration, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0); diff --git a/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js b/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js new file mode 100644 index 00000000000..9aeee2d44b5 --- /dev/null +++ b/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js @@ -0,0 +1,33 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Unbalancing handles DST days with more than 24 hours +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tz = TemporalHelpers.springForwardFallBackTimeZone(); + +// 2000-10-29 is a 25-hour day according to this time zone... + +const relativeTo = new Temporal.ZonedDateTime(941187600_000_000_000n, tz); + +// confirm that we have rewound one year and one day: +assert.sameValue('1999-10-29T01:00:00-08:00[Custom/Spring_Fall]', relativeTo.toString()); + +const d1 = new Temporal.Duration(1, 0, 0, 1); +const d2 = new Temporal.Duration(1, 0, 0, 0, 25); + +// ...so the durations should be equal relative to relativeTo: + +assert.sameValue(0, + Temporal.Duration.compare(d1, d2, { relativeTo }), + "2000-10-29 is a 25-hour day" +); + +assert.sameValue(1, + Temporal.Duration.compare(d1, { years: 1, hours: 24 }, { relativeTo }), + "2020-10-29 has more than 24 hours" +); diff --git a/test/built-ins/Temporal/Duration/days-undefined.js b/test/built-ins/Temporal/Duration/days-undefined.js index 716ad626f5a..f4072e0470b 100644 --- a/test/built-ins/Temporal/Duration/days-undefined.js +++ b/test/built-ins/Temporal/Duration/days-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.days, 0, "days default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.days, 0, "days default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/from/argument-existing-object.js b/test/built-ins/Temporal/Duration/from/argument-existing-object.js index 8173f7c96cd..7d0cb175023 100644 --- a/test/built-ins/Temporal/Duration/from/argument-existing-object.js +++ b/test/built-ins/Temporal/Duration/from/argument-existing-object.js @@ -4,16 +4,14 @@ /*--- esid: sec-temporal.duration.from description: Property bag is converted to Duration; Duration is copied +includes: [temporalHelpers.js] features: [Temporal] ---*/ -const d1 = Temporal.Duration.from({ milliseconds: 1000 }); -assert.sameValue(d1.seconds, 0); -assert.sameValue(d1.milliseconds, 1000); +const d1 = Temporal.Duration.from({ milliseconds: 1000, month: 1 }); +TemporalHelpers.assertDuration(d1, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); const d2 = Temporal.Duration.from(d1); assert.notSameValue(d1, d2); -assert.sameValue(d1.seconds, 0); -assert.sameValue(d1.milliseconds, 1000); -assert.sameValue(d2.seconds, 0); -assert.sameValue(d2.milliseconds, 1000); +TemporalHelpers.assertDuration(d1, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); +TemporalHelpers.assertDuration(d2, 0, 0, 0, 0, 0, 0, 0, 1000, 0, 0); diff --git a/test/built-ins/Temporal/Duration/from/argument-object-invalid.js b/test/built-ins/Temporal/Duration/from/argument-object-invalid.js new file mode 100644 index 00000000000..31818010fc9 --- /dev/null +++ b/test/built-ins/Temporal/Duration/from/argument-object-invalid.js @@ -0,0 +1,26 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Invalid object arguments. +features: [Temporal] +---*/ + +const tests = [ + { years: 0.5 }, + { months: 0.5 }, + { weeks: 0.5 }, + { days: 0.5 }, + { hours: 0.5, minutes: 20 }, + { hours: 0.5, seconds: 15 }, + { minutes: 10.7, nanoseconds: 400 }, + { hours: 1, minutes: -30 }, +]; + +for (const input of tests) { + assert.throws(RangeError, () => Temporal.Duration.from(input)); +} + +assert.throws(TypeError, () => Temporal.Duration.from({})); +assert.throws(TypeError, () => Temporal.Duration.from({ month: 12 })); diff --git a/test/built-ins/Temporal/Duration/from/argument-string-invalid.js b/test/built-ins/Temporal/Duration/from/argument-string-invalid.js new file mode 100644 index 00000000000..62708e2939b --- /dev/null +++ b/test/built-ins/Temporal/Duration/from/argument-string-invalid.js @@ -0,0 +1,32 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Invalid string arguments. +features: [Temporal] +---*/ + +const tests = [ + "P1Y1M1W1DT1H1M1.123456789123S", + "P0.5Y", + "P1Y0,5M", + "P1Y1M0.5W", + "P1Y1M1W0,5D", + "P1Y1M1W1DT0.5H5S", + "P1Y1M1W1DT1.5H0,5M", + "P1Y1M1W1DT1H0.5M0.5S", + "P", + "PT", + "-P", + "-PT", + "+P", + "+PT", + "P1Y1M1W1DT1H1M1.01Sjunk", + "P-1Y1M", + "P1Y-1M" +]; + +for (const input of tests) { + assert.throws(RangeError, () => Temporal.Duration.from(input)); +} diff --git a/test/built-ins/Temporal/Duration/from/argument-string.js b/test/built-ins/Temporal/Duration/from/argument-string.js new file mode 100644 index 00000000000..e41100b3d69 --- /dev/null +++ b/test/built-ins/Temporal/Duration/from/argument-string.js @@ -0,0 +1,48 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.from +description: Basic string arguments. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertDuration(Temporal.Duration.from("P1D"), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("p1y1m1dt1h1m1s"), + 1, 1, 0, 1, 1, 1, 1, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1S"), + 1, 1, 1, 1, 1, 1, 1, 100, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12S"), + 1, 1, 1, 1, 1, 1, 1, 120, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123S"), + 1, 1, 1, 1, 1, 1, 1, 123, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1234S"), + 1, 1, 1, 1, 1, 1, 1, 123, 400, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12345S"), + 1, 1, 1, 1, 1, 1, 1, 123, 450, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123456S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.1234567S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 700); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.12345678S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 780); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1.123456789S"), + 1, 1, 1, 1, 1, 1, 1, 123, 456, 789); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1Y1M1W1DT1H1M1,12S"), + 1, 1, 1, 1, 1, 1, 1, 120, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1DT0.5M"), + 0, 0, 0, 1, 0, 0, 30, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("P1DT0,5H"), + 0, 0, 0, 1, 0, 30, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("+P1D"), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("-P1D"), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("\u2212P1D"), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(Temporal.Duration.from("-P1Y1M1W1DT1H1M1.123456789S"), + -1, -1, -1, -1, -1, -1, -1, -123, -456, -789); +TemporalHelpers.assertDuration(Temporal.Duration.from("PT100M"), + 0, 0, 0, 0, 0, 100, 0, 0, 0, 0); diff --git a/test/built-ins/Temporal/Duration/hours-undefined.js b/test/built-ins/Temporal/Duration/hours-undefined.js index 26696569382..e068dee12c3 100644 --- a/test/built-ins/Temporal/Duration/hours-undefined.js +++ b/test/built-ins/Temporal/Duration/hours-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.hours, 0, "hours default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.hours, 0, "hours default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/microseconds-undefined.js b/test/built-ins/Temporal/Duration/microseconds-undefined.js index e0f92cb967c..1537ff75458 100644 --- a/test/built-ins/Temporal/Duration/microseconds-undefined.js +++ b/test/built-ins/Temporal/Duration/microseconds-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1, 1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.microseconds, 0, "microseconds default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.microseconds, 0, "microseconds default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/milliseconds-undefined.js b/test/built-ins/Temporal/Duration/milliseconds-undefined.js index c460c6a06ee..cee28885684 100644 --- a/test/built-ins/Temporal/Duration/milliseconds-undefined.js +++ b/test/built-ins/Temporal/Duration/milliseconds-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.milliseconds, 0, "milliseconds default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.milliseconds, 0, "milliseconds default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/minutes-undefined.js b/test/built-ins/Temporal/Duration/minutes-undefined.js index 265bd4fbc6b..562622ef7aa 100644 --- a/test/built-ins/Temporal/Duration/minutes-undefined.js +++ b/test/built-ins/Temporal/Duration/minutes-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.minutes, 0, "minutes default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.minutes, 0, "minutes default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/mixed.js b/test/built-ins/Temporal/Duration/mixed.js new file mode 100644 index 00000000000..5ba8517cf6f --- /dev/null +++ b/test/built-ins/Temporal/Duration/mixed.js @@ -0,0 +1,19 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration +description: Constructor with mixed signs. +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.Duration(-1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, -1, 1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, -1, 1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, -1, 1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, -1, 1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, -1, 1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, -1, 1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, -1, 1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1, -1, 1)); +assert.throws(RangeError, () => new Temporal.Duration(1, 1, 1, 1, 1, 1, 1, 1, 1, -1)); diff --git a/test/built-ins/Temporal/Duration/months-undefined.js b/test/built-ins/Temporal/Duration/months-undefined.js index f9cad3f216c..8ad0734831d 100644 --- a/test/built-ins/Temporal/Duration/months-undefined.js +++ b/test/built-ins/Temporal/Duration/months-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ -const years = 1; +const args = [1]; -const explicit = new Temporal.Duration(years, undefined); -assert.sameValue(explicit.months, 0, "months default argument"); +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); -const implicit = new Temporal.Duration(years); -assert.sameValue(implicit.months, 0, "months default argument"); +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/nanoseconds-undefined.js b/test/built-ins/Temporal/Duration/nanoseconds-undefined.js index 2d4de39199c..ec1d1518bba 100644 --- a/test/built-ins/Temporal/Duration/nanoseconds-undefined.js +++ b/test/built-ins/Temporal/Duration/nanoseconds-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1, 1, 1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.nanoseconds, 0, "nanoseconds default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.nanoseconds, 0, "nanoseconds default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/prototype/abs/basic.js b/test/built-ins/Temporal/Duration/prototype/abs/basic.js new file mode 100644 index 00000000000..ecc2ecf18a2 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/abs/basic.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Temporal.Duration.prototype.abs will return absolute value of the input duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). + +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.abs(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "empty"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "positive"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.abs(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, "large positive"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "negative"); + +// Test with some zeros +let d5 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d5.abs(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, "some zeros"); + +let d6 = new Temporal.Duration(0, 2, 0, 4, 0, 6, 0, 8, 0, 10); +TemporalHelpers.assertDuration( + d6.abs(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, "other zeros"); diff --git a/test/built-ins/Temporal/Duration/prototype/negated/basic.js b/test/built-ins/Temporal/Duration/prototype/negated/basic.js new file mode 100644 index 00000000000..f2bae4848a7 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/negated/basic.js @@ -0,0 +1,51 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Temporal.Duration.prototype.negated will return negated value of the input duration. +info: | + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.negated(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "zeros"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.negated(), -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + "positive values"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.negated(), -1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5, + "large positive values"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.negated(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + "negative values"); + +let d5 = new Temporal.Duration(-1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5); +TemporalHelpers.assertDuration( + d5.negated(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, + "large negative values"); + +let d6 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d6.negated(), -1, 0, -3, 0, -5, 0, -7, 0, -9, 0, + "some zeros with positive values"); + +let d7 = new Temporal.Duration(-1, 0, -3, 0, -5, 0, -7, 0, -9, 0); +TemporalHelpers.assertDuration( + d7.negated(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, + "some zeros with negative values"); + +let d8 = new Temporal.Duration(0, -2, 0, -4, 0, -6, 0, -8, 0, -10); +TemporalHelpers.assertDuration( + d8.negated(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, + "other zeros with negative values"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js index 35a9df28076..e895dd70f02 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => duration.round({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js b/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js new file mode 100644 index 00000000000..8cadc51661c --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js @@ -0,0 +1,240 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.prototype.toJSON will return correct iso8601 string for the given duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "auto"). +features: [Temporal] +---*/ + +let d = new Temporal.Duration(); +assert.sameValue(d.toJSON(), "PT0S", "zero duration"); + +d = new Temporal.Duration(1); +assert.sameValue(d.toJSON(), "P1Y", "positive small years"); +d = new Temporal.Duration(-1); +assert.sameValue(d.toJSON(), "-P1Y", "negative small years"); +d = new Temporal.Duration(1234567890); +assert.sameValue(d.toJSON(), "P1234567890Y", "positive large years"); +d = new Temporal.Duration(-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890Y", "negative large years"); + +d = new Temporal.Duration(1, 2); +assert.sameValue(d.toJSON(), "P1Y2M", "positive years and months"); +d = new Temporal.Duration(-1, -2); +assert.sameValue(d.toJSON(), "-P1Y2M", "negative years and months"); +d = new Temporal.Duration(0, 2); +assert.sameValue(d.toJSON(), "P2M", "positive small months"); +d = new Temporal.Duration(0,-2); +assert.sameValue(d.toJSON(), "-P2M", "negative small months"); +d = new Temporal.Duration(0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890M", "positive large months"); +d = new Temporal.Duration(0,-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890M", "negative large months"); + +d = new Temporal.Duration(1, 2, 3); +assert.sameValue(d.toJSON(), "P1Y2M3W", "positive years, months, weeks"); +d = new Temporal.Duration(-1, -2, -3); +assert.sameValue(d.toJSON(), "-P1Y2M3W", "negative years, months, weeks"); +d = new Temporal.Duration(0, 0, 3); +assert.sameValue(d.toJSON(), "P3W", "positive small weeks"); +d = new Temporal.Duration(0, 0, -3); +assert.sameValue(d.toJSON(), "-P3W", "negative small weeks"); +d = new Temporal.Duration(1, 0, 3); +assert.sameValue(d.toJSON(), "P1Y3W", "positive years and weeks"); +d = new Temporal.Duration(-1, 0, -3); +assert.sameValue(d.toJSON(), "-P1Y3W", "negative years and weeks"); +d = new Temporal.Duration(0, 2, 3); +assert.sameValue(d.toJSON(), "P2M3W", "positive months and weeks"); +d = new Temporal.Duration(0, -2, -3); +assert.sameValue(d.toJSON(), "-P2M3W", "negative months and weeks"); +d = new Temporal.Duration(0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890W", "positive large weeks"); +d = new Temporal.Duration(0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890W", "negative large weeks"); + +d = new Temporal.Duration(1, 2, 3, 4); +assert.sameValue(d.toJSON(), "P1Y2M3W4D", "positive years, months, weeks, days"); +d = new Temporal.Duration(-1, -2, -3, -4); +assert.sameValue(d.toJSON(), "-P1Y2M3W4D", "negative years, months, weeks, days"); +d = new Temporal.Duration(0, 0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890D", "positive large days"); +d = new Temporal.Duration(0, 0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890D", "negative large days"); +d = new Temporal.Duration(0, 0, 0, 4); +assert.sameValue(d.toJSON(), "P4D", "positive small days"); +d = new Temporal.Duration(0, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P4D", "negative small days"); +d = new Temporal.Duration(1, 0, 0, 4); +assert.sameValue(d.toJSON(), "P1Y4D", "positive years and days"); +d = new Temporal.Duration(-1, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P1Y4D", "negative years and days"); +d = new Temporal.Duration(0, 2, 0, 4); +assert.sameValue(d.toJSON(), "P2M4D", "positive months and days"); +d = new Temporal.Duration(0, -2, 0, -4); +assert.sameValue(d.toJSON(), "-P2M4D", "negative months and days"); +d = new Temporal.Duration(0, 0, 3, 4); +assert.sameValue(d.toJSON(), "P3W4D", "positive weeks and days"); +d = new Temporal.Duration(0, 0, -3, -4); +assert.sameValue(d.toJSON(), "-P3W4D", "negative weeks and days"); + +d = new Temporal.Duration(0, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "PT5H", "positive hours"); +d = new Temporal.Duration(0, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-PT5H", "negative hours"); +d = new Temporal.Duration(1, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "P1YT5H", "positive years and hours"); +d = new Temporal.Duration(-1, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P1YT5H", "negative years and hours"); +d = new Temporal.Duration(0, 2, 0, 0, 5); +assert.sameValue(d.toJSON(), "P2MT5H", "positive months and hours"); +d = new Temporal.Duration(0, -2, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P2MT5H", "negative months and hours"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 6); +assert.sameValue(d.toJSON(), "PT6M", "positive minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6); +assert.sameValue(d.toJSON(), "-PT6M", "negative minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6); +assert.sameValue(d.toJSON(), "PT5H6M", "positive hours and minutes"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6); +assert.sameValue(d.toJSON(), "-PT5H6M", "negative hours and minutes"); +d = new Temporal.Duration(0, 0, 3, 0, 0, 6); +assert.sameValue(d.toJSON(), "P3WT6M", "positive weeks and minutes"); +d = new Temporal.Duration(0, 0, -3, 0, 0, -6); +assert.sameValue(d.toJSON(), "-P3WT6M", "negative weeks and minutes"); +d = new Temporal.Duration(0, 0, 0, 4, 0, 6); +assert.sameValue(d.toJSON(), "P4DT6M", "positive days and minutes"); +d = new Temporal.Duration(0, 0, 0, -4, 0, -6); +assert.sameValue(d.toJSON(), "-P4DT6M", "negative days and minutes"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 7); +assert.sameValue(d.toJSON(), "PT7S", "positive seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -7); +assert.sameValue(d.toJSON(), "-PT7S", "negative seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 0, 7); +assert.sameValue(d.toJSON(), "PT5H7S", "positive hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, 0, -7); +assert.sameValue(d.toJSON(), "-PT5H7S", "negative hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 6, 7); +assert.sameValue(d.toJSON(), "PT6M7S", "positive minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6, -7); +assert.sameValue(d.toJSON(), "-PT6M7S", "negative minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "PT5H6M7S", "positive hours, minutes, seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-PT5H6M7S", "negative hours, minutes, seconds"); +d = new Temporal.Duration(1, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "P1YT5H6M7S", "positive years, hours, minutes, seconds"); +d = new Temporal.Duration(-1, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-P1YT5H6M7S", "negative years, hours, minutes, seconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 8); +assert.sameValue(d.toJSON(), "PT0.008S", "positive milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -8); +assert.sameValue(d.toJSON(), "-PT0.008S", "negative milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 80); +assert.sameValue(d.toJSON(), "PT0.08S", "positive milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -80); +assert.sameValue(d.toJSON(), "-PT0.08S", "negative milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 87); +assert.sameValue(d.toJSON(), "PT0.087S", "positive two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -87); +assert.sameValue(d.toJSON(), "-PT0.087S", "negative two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876); +assert.sameValue(d.toJSON(), "PT0.876S", "positive three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876); +assert.sameValue(d.toJSON(), "-PT0.876S", "negative three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876543); +assert.sameValue(d.toJSON(), "PT876.543S", "positive large milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876543); +assert.sameValue(d.toJSON(), "-PT876.543S", "negative large milliseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 9); +assert.sameValue(d.toJSON(), "PT0.000009S", "positive microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -9); +assert.sameValue(d.toJSON(), "-PT0.000009S", "negative microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 90); +assert.sameValue(d.toJSON(), "PT0.00009S", "positive microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -90); +assert.sameValue(d.toJSON(), "-PT0.00009S", "negative microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 98); +assert.sameValue(d.toJSON(), "PT0.000098S", "positive two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -98); +assert.sameValue(d.toJSON(), "-PT0.000098S", "negative two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 900); +assert.sameValue(d.toJSON(), "PT0.0009S", "positive microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -900); +assert.sameValue(d.toJSON(), "-PT0.0009S", "negative microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987); +assert.sameValue(d.toJSON(), "PT0.000987S", "positive three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987); +assert.sameValue(d.toJSON(), "-PT0.000987S", "negative three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654); +assert.sameValue(d.toJSON(), "PT0.987654S", "positive large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654); +assert.sameValue(d.toJSON(), "-PT0.987654S", "negative large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654321); +assert.sameValue(d.toJSON(), "PT987.654321S", "positive larger microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654321); +assert.sameValue(d.toJSON(), "-PT987.654321S", "negative larger microseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1); +assert.sameValue(d.toJSON(), "PT0.000000001S", "positive nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1); +assert.sameValue(d.toJSON(), "-PT0.000000001S", "negative nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 10); +assert.sameValue(d.toJSON(), "PT0.00000001S", "positive nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -10); +assert.sameValue(d.toJSON(), "-PT0.00000001S", "negative nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 12); +assert.sameValue(d.toJSON(), "PT0.000000012S", "positive two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -12); +assert.sameValue(d.toJSON(), "-PT0.000000012S", "negative two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 100); +assert.sameValue(d.toJSON(), "PT0.0000001S", "positive nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -100); +assert.sameValue(d.toJSON(), "-PT0.0000001S", "negative nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123); +assert.sameValue(d.toJSON(), "PT0.000000123S", "positive three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123); +assert.sameValue(d.toJSON(), "-PT0.000000123S", "negative three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456); +assert.sameValue(d.toJSON(), "PT0.000123456S", "positive large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456); +assert.sameValue(d.toJSON(), "-PT0.000123456S", "negative large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456789); +assert.sameValue(d.toJSON(), "PT0.123456789S", "positive larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456789); +assert.sameValue(d.toJSON(), "-PT0.123456789S", "negative larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1234567891); +assert.sameValue(d.toJSON(), "PT1.234567891S", "positive even larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1234567891); +assert.sameValue(d.toJSON(), "-PT1.234567891S", "negative even larger nanoseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1); +assert.sameValue(d.toJSON(), "PT4.003002001S", "positive seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1); +assert.sameValue(d.toJSON(), "-PT4.003002001S", "negative seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90001); +assert.sameValue(d.toJSON(), "PT4.003092001S", "positive seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90001); +assert.sameValue(d.toJSON(), "-PT4.003092001S", "negative seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90080001); +assert.sameValue(d.toJSON(), "PT4.093082001S", "positive seconds and larger subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90080001); +assert.sameValue(d.toJSON(), "-PT4.093082001S", "negative seconds and larger subseconds"); + +d = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 1); +assert.sameValue(d.toJSON(), "P1Y2M3W4DT5H6M7.008009001S", "all fields positive"); +d = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -1); +assert.sameValue(d.toJSON(), "-P1Y2M3W4DT5H6M7.008009001S", "all fields negative"); + +d = new Temporal.Duration(1234, 2345, 3456, 4567, 5678, 6789, 7890, 890, 901, 123); +assert.sameValue(d.toJSON(), "P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and positive"); +d = new Temporal.Duration(-1234, -2345, -3456, -4567, -5678, -6789, -7890, -890, -901, -123); +assert.sameValue(d.toJSON(), "-P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and negative"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/balance.js b/test/built-ins/Temporal/Duration/prototype/toString/balance.js new file mode 100644 index 00000000000..f66832a0c95 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/balance.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: Verify that values are balanced correctly. +features: [Temporal] +---*/ + +assert.sameValue( + Temporal.Duration.from({ milliseconds: 3500 }).toString(), + "PT3.5S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: 3500 }).toString(), + "PT0.0035S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: 3500 }).toString(), + "PT0.0000035S"); +assert.sameValue( + new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 1111, 1111, 1111).toString(), + "PT1.112112111S"); +assert.sameValue( + Temporal.Duration.from({ seconds: 120, milliseconds: 3500 }).toString(), + "PT123.5S"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js index 1cb51f820eb..036b977ad16 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js @@ -16,4 +16,6 @@ features: [Temporal] const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); -assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: "other string" })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos"]) { + assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits })); +} diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js index d9f4837d3cb..9a20541c19f 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js @@ -16,5 +16,7 @@ features: [Temporal] const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -Infinity })); assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -1 })); assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: Infinity })); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/negative-components.js b/test/built-ins/Temporal/Duration/prototype/toString/negative-components.js index 7bfc8232a52..2022f4bd4f4 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/negative-components.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/negative-components.js @@ -6,6 +6,33 @@ esid: sec-temporal.duration.prototype.tostring description: Temporal.Duration.toString handles negative components features: [Temporal] ---*/ -const d = new Temporal.Duration(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1); -const expected = "-P1Y1M1W1DT1H1M1.001001001S"; -assert.sameValue(d.toString(), expected, "toString with negative components"); +assert.sameValue( + new Temporal.Duration(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1).toString(), + "-P1Y1M1W1DT1H1M1.001001001S"); +assert.sameValue( + Temporal.Duration.from({ milliseconds: -250 }).toString(), + "-PT0.25S"); +assert.sameValue( + Temporal.Duration.from({ milliseconds: -3500 }).toString(), + "-PT3.5S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: -250 }).toString(), + "-PT0.00025S"); +assert.sameValue( + Temporal.Duration.from({ microseconds: -3500 }).toString(), + "-PT0.0035S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: -250 }).toString(), + "-PT0.00000025S"); +assert.sameValue( + Temporal.Duration.from({ nanoseconds: -3500 }).toString(), + "-PT0.0000035S"); +assert.sameValue( + new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -1111, -1111, -1111).toString(), + "-PT1.112112111S"); +assert.sameValue( + Temporal.Duration.from({ seconds: -120, milliseconds: -3500 }).toString(), + "-PT123.5S"); +assert.sameValue( + Temporal.Duration.from({ weeks: -1, days: -1 }).toString(), + "-P1W1D"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js index 983b9a25b67..f1015122ce9 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => duration.toString({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js index b41620c1f4d..046b4a99f70 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js @@ -8,4 +8,7 @@ features: [Temporal] ---*/ const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => duration.toString({ smallestUnit: "other string" })); +const values = ["eras", "years", "months", "weeks", "days", "hours", "minutes", "nonsense", "other string", "mill\u0131seconds", "SECONDS"]; +for (const smallestUnit of values) { + assert.throws(RangeError, () => duration.toString({ smallestUnit })); +} diff --git a/test/built-ins/Temporal/Duration/prototype/with/all-negative.js b/test/built-ins/Temporal/Duration/prototype/with/all-negative.js new file mode 100644 index 00000000000..e094455bb8e --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/all-negative.js @@ -0,0 +1,93 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all negative values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllNegative = { + years: -9, + months: -8, + weeks: -7, + days: -6, + hours: -5, + minutes: -4, + seconds: -3, + milliseconds: -2, + microseconds: -1, + nanoseconds: -10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all zeroes with all negative" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive with all negative" +); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive large numbers with all negative" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all negative with all negative" +); diff --git a/test/built-ins/Temporal/Duration/prototype/with/all-positive.js b/test/built-ins/Temporal/Duration/prototype/with/all-positive.js new file mode 100644 index 00000000000..21584232fc0 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/all-positive.js @@ -0,0 +1,92 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllPositive = { + years: 9, + months: 8, + weeks: 7, + days: 6, + hours: 5, + minutes: 4, + seconds: 3, + milliseconds: 2, + microseconds: 1, + nanoseconds: 10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all zeroes with all positive" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive with all positive"); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive large numbers with all positive" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all negative with all positive" +); diff --git a/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js b/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js new file mode 100644 index 00000000000..5c17076bec5 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + The durationLike argument must contain at least one correctly spelled property +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + {}, + [], + () => {}, + // objects with only singular keys (plural is the correct spelling) + { year: 1 }, + { month: 2 }, + { week: 3 }, + { day: 4 }, + { hour: 5 }, + { minute: 6 }, + { second: 7 }, + { millisecond: 8 }, + { microsecond: 9 }, + { nanosecond: 10 }, +].forEach((badObject) => { + assert.throws(TypeError, () => d.with(badObject), + "Throw TypeError if temporalDurationLike is not valid"); +}); diff --git a/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js new file mode 100644 index 00000000000..41163a35da6 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw TypeError if the temporalDurationLike argument is the wrong type +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + "string", + "P1YT1M", + true, + false, + NaN, + Infinity, + undefined, + null, + 123, + Symbol(), + 456n, +].forEach((badInput) => { + assert.throws(TypeError, () => d.with(badInput), + "Throw TypeError if temporalDurationLike is not valid"); +}); diff --git a/test/built-ins/Temporal/Duration/prototype/with/branding.js b/test/built-ins/Temporal/Duration/prototype/with/branding.js index 2bc9af85bf8..b04b2fefd60 100644 --- a/test/built-ins/Temporal/Duration/prototype/with/branding.js +++ b/test/built-ins/Temporal/Duration/prototype/with/branding.js @@ -11,12 +11,14 @@ const with_ = Temporal.Duration.prototype.with; assert.sameValue(typeof with_, "function"); -assert.throws(TypeError, () => with_.call(undefined), "undefined"); -assert.throws(TypeError, () => with_.call(null), "null"); -assert.throws(TypeError, () => with_.call(true), "true"); -assert.throws(TypeError, () => with_.call(""), "empty string"); -assert.throws(TypeError, () => with_.call(Symbol()), "symbol"); -assert.throws(TypeError, () => with_.call(1), "1"); -assert.throws(TypeError, () => with_.call({}), "plain object"); -assert.throws(TypeError, () => with_.call(Temporal.Duration), "Temporal.Duration"); -assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype), "Temporal.Duration.prototype"); +const arg = { years: 3 }; + +assert.throws(TypeError, () => with_.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => with_.call(null, arg), "null"); +assert.throws(TypeError, () => with_.call(true, arg), "true"); +assert.throws(TypeError, () => with_.call("", arg), "empty string"); +assert.throws(TypeError, () => with_.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => with_.call(1, arg), "1"); +assert.throws(TypeError, () => with_.call({}, arg), "plain object"); +assert.throws(TypeError, () => with_.call(Temporal.Duration, arg), "Temporal.Duration"); +assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype, arg), "Temporal.Duration.prototype"); diff --git a/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js b/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js new file mode 100644 index 00000000000..b1425de497f --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js @@ -0,0 +1,86 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces only some of the + fields with positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const durationlike1 = { years: 9, hours: 5 }; +const durationlike2 = { months: 8, minutes: 4 }; +const durationlike3 = { weeks: 7, seconds: 3 }; +const durationlike4 = { days: 6, milliseconds: 2 }; +const durationlike5 = { microseconds: 987, nanoseconds: 123 }; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(durationlike1), 9, 0, 0, 0, 5, 0, 0, 0, 0, 0, "replace all zeroes with years and hours"); +TemporalHelpers.assertDuration( + d1.with(durationlike2), 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, "replace all zeroes wtih months and minutes"); +TemporalHelpers.assertDuration( + d1.with(durationlike3), 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, "replace all zeroes with weeks and seconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike4), 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, "replace all zeroes with days and milliseconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike5), 0, 0, 0, 0, 0, 0, 0, 0, 987, 123, "replace all zeroes with microseconds and nanoseconds"); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(durationlike1), 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, "replace all positive with years and hours"); +TemporalHelpers.assertDuration( + d2.with(durationlike2), 1, 8, 3, 4, 5, 4, 7, 8, 9, 10, "replace all positive with months and minutes"); +TemporalHelpers.assertDuration( + d2.with(durationlike3), 1, 2, 7, 4, 5, 6, 3, 8, 9, 10, "replace all positive with weeks and seconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike4), 1, 2, 3, 6, 5, 6, 7, 2, 9, 10, "replace all positive with days and milliseconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike5), 1, 2, 3, 4, 5, 6, 7, 8, 987, 123, "replace all positive with microseconds and nanoseconds"); diff --git a/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js b/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js new file mode 100644 index 00000000000..239951b34d1 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw RangeError if the resulting duration has mixed signs +info: | + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +---*/ + +const d1 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +const d2 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +fields.forEach((field) => { + assert.throws( + RangeError, + () => d1.with({ [field]: -1 }), + `sign in argument { ${field}: -1 } conflicting with sign of duration should throw RangeError` + ); + + assert.throws( + RangeError, + () => d2.with({ [field]: 1 }), + `sign in argument { ${field}: 1 } conflicting with sign of duration should throw RangeError` + ); +}); diff --git a/test/built-ins/Temporal/Duration/seconds-undefined.js b/test/built-ins/Temporal/Duration/seconds-undefined.js index a4cc4add4a0..e3cd9b15b22 100644 --- a/test/built-ins/Temporal/Duration/seconds-undefined.js +++ b/test/built-ins/Temporal/Duration/seconds-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1, 1, 1, 1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.seconds, 0, "seconds default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.seconds, 0, "seconds default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/weeks-undefined.js b/test/built-ins/Temporal/Duration/weeks-undefined.js index d01172db2d3..12c03332d05 100644 --- a/test/built-ins/Temporal/Duration/weeks-undefined.js +++ b/test/built-ins/Temporal/Duration/weeks-undefined.js @@ -4,13 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [1, 1]; const explicit = new Temporal.Duration(...args, undefined); -assert.sameValue(explicit.weeks, 0, "weeks default argument"); +TemporalHelpers.assertDuration(explicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); const implicit = new Temporal.Duration(...args); -assert.sameValue(implicit.weeks, 0, "weeks default argument"); +TemporalHelpers.assertDuration(implicit, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Duration/years-undefined.js b/test/built-ins/Temporal/Duration/years-undefined.js index 55235840916..c0fb9cea21e 100644 --- a/test/built-ins/Temporal/Duration/years-undefined.js +++ b/test/built-ins/Temporal/Duration/years-undefined.js @@ -4,11 +4,14 @@ /*--- esid: sec-temporal.duration description: Undefined arguments should be treated as zero. +includes: [temporalHelpers.js] features: [Temporal] ---*/ -const explicit = new Temporal.Duration(undefined); -assert.sameValue(explicit.years, 0, "years default argument"); +const args = []; -const implicit = new Temporal.Duration(); -assert.sameValue(implicit.years, 0, "years default argument"); +const explicit = new Temporal.Duration(...args, undefined); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.Duration(...args); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "implicit"); diff --git a/test/built-ins/Temporal/Instant/prototype/add/basic.js b/test/built-ins/Temporal/Instant/prototype/add/basic.js new file mode 100644 index 00000000000..1b94ba1befb --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/add/basic.js @@ -0,0 +1,72 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: Basic functionality of Temporal.Instant.prototype.add() +info: | + 1. Let instant be the this value. + 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). + 4. Let ns be ? AddInstant(instant.[[EpochNanoseconds]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]). + 5. Return ! CreateTemporalInstant(ns). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(50000n); + +let result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 3, 2, 1)); +assert.sameValue( + 3052001n, + result.epochNanoseconds, + "add positive sub-seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1)); +assert.sameValue( + BigInt(4 * 1e9) + 3052001n, + result.epochNanoseconds, + "add positive seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "add positive minutes" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 6, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "add positive hours" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -3, -2, -1)); +assert.sameValue( + -2952001n, + result.epochNanoseconds, + "add negative sub-seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1)); +assert.sameValue( + BigInt(-4 * 1e9) - 2952001n, + result.epochNanoseconds, + "add negative seconds" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, 0, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "add negative minutes" +); + +result = inst.add(new Temporal.Duration(0, 0, 0, 0, -6, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "add negative hours" +); diff --git a/test/built-ins/Temporal/Instant/prototype/add/branding.js b/test/built-ins/Temporal/Instant/prototype/add/branding.js index cb6b1158c6d..cccdbf63ef1 100644 --- a/test/built-ins/Temporal/Instant/prototype/add/branding.js +++ b/test/built-ins/Temporal/Instant/prototype/add/branding.js @@ -11,12 +11,14 @@ const add = Temporal.Instant.prototype.add; assert.sameValue(typeof add, "function"); -assert.throws(TypeError, () => add.call(undefined), "undefined"); -assert.throws(TypeError, () => add.call(null), "null"); -assert.throws(TypeError, () => add.call(true), "true"); -assert.throws(TypeError, () => add.call(""), "empty string"); -assert.throws(TypeError, () => add.call(Symbol()), "symbol"); -assert.throws(TypeError, () => add.call(1), "1"); -assert.throws(TypeError, () => add.call({}), "plain object"); -assert.throws(TypeError, () => add.call(Temporal.Instant), "Temporal.Instant"); -assert.throws(TypeError, () => add.call(Temporal.Instant.prototype), "Temporal.Instant.prototype"); +const arg = new Temporal.Duration(0, 0, 0, 0, 5); + +assert.throws(TypeError, () => add.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => add.call(null, arg), "null"); +assert.throws(TypeError, () => add.call(true, arg), "true"); +assert.throws(TypeError, () => add.call("", arg), "empty string"); +assert.throws(TypeError, () => add.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => add.call(1, arg), "1"); +assert.throws(TypeError, () => add.call({}, arg), "plain object"); +assert.throws(TypeError, () => add.call(Temporal.Instant, arg), "Temporal.Instant"); +assert.throws(TypeError, () => add.call(Temporal.Instant.prototype, arg), "Temporal.Instant.prototype"); diff --git a/test/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js b/test/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js new file mode 100644 index 00000000000..f6e35389cd8 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/add/disallowed-duration-units.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.add +description: | + Temporal.Instant.prototype.add() throws RangeError when the duration has + non-zero years, months, weeks, or days. +info: | + 1. Let instant be the this value. + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(500000n); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(1)), + "should throw RangeError when the duration has non-zero years (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 2)), + "should throw RangeError when the duration has non-zero months (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 3)), + "should throw RangeError when the duration has non-zero weeks (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 0, 4)), + "should throw RangeError when the duration has non-zero days (positive)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(-1)), + "should throw RangeError when the duration has non-zero years (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, -2)), + "should throw RangeError when the duration has non-zero months (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, -3)), + "should throw RangeError when the duration has non-zero weeks (negative)"); +assert.throws(RangeError, () => inst.add(new Temporal.Duration(0, 0, 0, -4)), + "should throw RangeError when the duration has non-zero days (negative)"); diff --git a/test/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js b/test/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js index 63f6bba22a3..a2473233c8d 100644 --- a/test/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js +++ b/test/built-ins/Temporal/Instant/prototype/add/result-out-of-range.js @@ -9,8 +9,22 @@ features: [Temporal] const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; -const instance = Temporal.Instant.fromEpochNanoseconds(8640000_000_000_000_000_000n); +const latest = Temporal.Instant.fromEpochNanoseconds(8640000_000_000_000_000_000n); fields.forEach((field) => { - assert.throws(RangeError, () => instance.add({ [field]: 1 })); + assert.throws( + RangeError, + () => latest.add({ [field]: 1 }), + `adding ${field} with result out of range (positive)` + ); +}); + +const earliest = Temporal.Instant.fromEpochNanoseconds(-8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => earliest.add({ [field]: -1 }), + `adding ${field} with result out of range (negative)` + ); }); diff --git a/test/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js index 7f3ed29f4a2..a826b1e72e2 100644 --- a/test/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/round/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_123_987_500n); -assert.throws(RangeError, () => instant.round({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => instant.round({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js index 66f94cf2ca1..27771f28e8c 100644 --- a/test/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/since/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/Instant/prototype/subtract/basic.js b/test/built-ins/Temporal/Instant/prototype/subtract/basic.js new file mode 100644 index 00000000000..36fa8544520 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/subtract/basic.js @@ -0,0 +1,72 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: Basic functionality of Temporal.Instant.prototype.subtract() +info: | + 1. Let instant be the this value. + 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). + 4. Let ns be ? AddInstant(instant.[[EpochNanoseconds]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]). + 5. Return ! CreateTemporalInstant(ns). +features: [Temporal] +---*/ + +const inst = new Temporal.Instant(50000n); + +let result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 3, 2, 1)); +assert.sameValue( + -2952001n, + result.epochNanoseconds, + "subtract positive sub-seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1)); +assert.sameValue( + BigInt(-4 * 1e9) - 2952001n, + result.epochNanoseconds, + "subtract positive seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "subtract positive minutes" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 6, 5, 4, 3, 2, 1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * -1000000000n - 2952001n, + result.epochNanoseconds, + "subtract positive hours" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -3, -2, -1)); +assert.sameValue( + 3052001n, + result.epochNanoseconds, + "subtract negative sub-seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1)); +assert.sameValue( + BigInt(4 * 1e9) + 3052001n, + result.epochNanoseconds, + "subtract negative seconds" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, 0, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "subtract negative minutes" +); + +result = inst.subtract(new Temporal.Duration(0, 0, 0, 0, -6, -5, -4, -3, -2, -1)); +assert.sameValue( + BigInt(6 * 3600 + 5 * 60 + 4) * 1000000000n + 3052001n, + result.epochNanoseconds, + "subtract negative hours" +); diff --git a/test/built-ins/Temporal/Instant/prototype/subtract/branding.js b/test/built-ins/Temporal/Instant/prototype/subtract/branding.js index d7c307e3f9f..a7aac12b9c2 100644 --- a/test/built-ins/Temporal/Instant/prototype/subtract/branding.js +++ b/test/built-ins/Temporal/Instant/prototype/subtract/branding.js @@ -11,12 +11,14 @@ const subtract = Temporal.Instant.prototype.subtract; assert.sameValue(typeof subtract, "function"); -assert.throws(TypeError, () => subtract.call(undefined), "undefined"); -assert.throws(TypeError, () => subtract.call(null), "null"); -assert.throws(TypeError, () => subtract.call(true), "true"); -assert.throws(TypeError, () => subtract.call(""), "empty string"); -assert.throws(TypeError, () => subtract.call(Symbol()), "symbol"); -assert.throws(TypeError, () => subtract.call(1), "1"); -assert.throws(TypeError, () => subtract.call({}), "plain object"); -assert.throws(TypeError, () => subtract.call(Temporal.Instant), "Temporal.Instant"); -assert.throws(TypeError, () => subtract.call(Temporal.Instant.prototype), "Temporal.Instant.prototype"); +const arg = new Temporal.Duration(0, 0, 0, 0, 5); + +assert.throws(TypeError, () => subtract.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => subtract.call(null, arg), "null"); +assert.throws(TypeError, () => subtract.call(true, arg), "true"); +assert.throws(TypeError, () => subtract.call("", arg), "empty string"); +assert.throws(TypeError, () => subtract.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => subtract.call(1, arg), "1"); +assert.throws(TypeError, () => subtract.call({}, arg), "plain object"); +assert.throws(TypeError, () => subtract.call(Temporal.Instant, arg), "Temporal.Instant"); +assert.throws(TypeError, () => subtract.call(Temporal.Instant.prototype, arg), "Temporal.Instant.prototype"); diff --git a/test/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js b/test/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js new file mode 100644 index 00000000000..9a8cf9ae0e7 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.subtract +description: | + Temporal.Instant.prototype.subtract() throws RangeError when the duration has + non-zero years, months, weeks or days. +info: | + 1. Let instant be the this value. + 3. Let duration be ? ToLimitedTemporalDuration(temporalDurationLike, « "years", "months", "weeks", "days" »). +features: [Temporal] +---*/ + +let i1 = new Temporal.Instant(500000n); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(1)), + "should throw RangeError when the duration has non-zero years (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 2)), + "should throw RangeError when the duration has non-zero months (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 3)), + "should throw RangeError when the duration has non-zero weeks (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 0, 4)), + "should throw RangeError when the duration has non-zero days (positive)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(-1)), + "should throw RangeError when the duration has non-zero years (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, -2)), + "should throw RangeError when the duration has non-zero months (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, -3)), + "should throw RangeError when the duration has non-zero weeks (negative)"); +assert.throws(RangeError, () => i1.subtract(new Temporal.Duration(0, 0, 0, -4)), + "should throw RangeError when the duration has non-zero days (negative)"); diff --git a/test/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js b/test/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js index 83804b758c4..82702dea68d 100644 --- a/test/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js +++ b/test/built-ins/Temporal/Instant/prototype/subtract/result-out-of-range.js @@ -2,15 +2,29 @@ // This code is governed by the BSD license found in the LICENSE file. /*--- -esid: sec-temporal.instant.prototype.add +esid: sec-temporal.instant.prototype.subtract description: RangeError thrown if result is outside representable range features: [Temporal] ---*/ const fields = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; -const instance = Temporal.Instant.fromEpochNanoseconds(-8640000_000_000_000_000_000n); +const earliest = Temporal.Instant.fromEpochNanoseconds(-8640000_000_000_000_000_000n); fields.forEach((field) => { - assert.throws(RangeError, () => instance.subtract({ [field]: 1 })); + assert.throws( + RangeError, + () => earliest.subtract({ [field]: 1 }), + `subtracting ${field} with result out of range (negative)` + ); +}); + +const latest = Temporal.Instant.fromEpochNanoseconds(8640000_000_000_000_000_000n); + +fields.forEach((field) => { + assert.throws( + RangeError, + () => latest.subtract({ [field]: -1 }), + `subtracting ${field} with result out of range (positive)` + ); }); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js index 4a4099b108f..6bff72f3b3d 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_123_987_500n); -assert.throws(RangeError, () => instant.toString({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => instant.toString({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js index fc8aaed464f..82a212cafd8 100644 --- a/test/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/until/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js new file mode 100644 index 00000000000..8c0480b1d1a --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js @@ -0,0 +1,66 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const other = new Temporal.PlainDate(2020, 1, 1); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js index f0dee3ade9c..b59bdf35d49 100644 --- a/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js +++ b/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js @@ -1,30 +1,60 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.plaindate.from -description: overflow property is extracted with ISO-invalid string argument. -info: | - 1. Perform ? ToTemporalOverflow(_options_). - - 1. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. -includes: [compareArray.js, temporalHelpers.js] -features: [Temporal] +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] ---*/ -const expected = [ - "get overflow", - "get overflow.toString", - "call overflow.toString", +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", ]; - -let actual = []; -const object = { - get overflow() { - actual.push("get overflow"); - return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); - } -}; - -assert.throws(RangeError, () => Temporal.PlainDate.from("2020-13-34", object)); -assert.compareArray(actual, expected); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js new file mode 100644 index 00000000000..f0dee3ade9c --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.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.plaindate.from +description: overflow property is extracted with ISO-invalid string argument. +info: | + 1. Perform ? ToTemporalOverflow(_options_). + + 1. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; + +let actual = []; +const object = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); + } +}; + +assert.throws(RangeError, () => Temporal.PlainDate.from("2020-13-34", object)); +assert.compareArray(actual, expected); diff --git a/test/built-ins/Temporal/PlainDate/from/argument-string-overflow.js b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js similarity index 100% rename from test/built-ins/Temporal/PlainDate/from/argument-string-overflow.js rename to test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js diff --git a/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js index f04f77f745b..27e499961c5 100644 --- a/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js @@ -34,8 +34,14 @@ const invalidOverflow = [ "CONSTRAIN", "constra\u0131n", ]; -validItems.forEach((item) => { - invalidOverflow.forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainDate.from(item, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const item of validItems) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(item, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js index 66282d2a6c3..6c7b65fd879 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js @@ -18,6 +18,12 @@ features: [Temporal] const date = new Temporal.PlainDate(2000, 5, 2); const duration = new Temporal.Duration(3, 3, 0, 3); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => date.add(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js new file mode 100644 index 00000000000..ca71e4016a9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.equals(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js new file mode 100644 index 00000000000..45e74d668a5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.since(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js index cf9d9e20c7a..8aeeb567342 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js index d3cbd6e8074..9387c6aff46 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js @@ -18,6 +18,12 @@ features: [Temporal] const date = new Temporal.PlainDate(2000, 5, 2); const duration = new Temporal.Duration(3, 3, 0, 3); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => date.subtract(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js new file mode 100644 index 00000000000..4e59ac5e3f3 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.until(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js index 2ed4da16bb6..9139e8c1519 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js index d35f66be86b..acef874825b 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const date = new Temporal.PlainDate(2000, 5, 2); -["", "CONSTRAIN", "balance", "other string"].forEach((overflow) => - assert.throws(RangeError, () => date.with({ month: 8 }, { overflow })) -); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js new file mode 100644 index 00000000000..5ef97473d64 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/compare/argument-object-insufficient-data.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Plain object arguments may throw if they do not contain sufficient information +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare({ year: 1976 }, dt2), + "object must contain at least the required properties (first arg)" +); + +assert.throws( + TypeError, + () => Temporal.PlainDateTime.compare(dt1, { year: 2019 }), + "object must contain at least the required properties (second arg)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/compare/basic.js b/test/built-ins/Temporal/PlainDateTime/compare/basic.js new file mode 100644 index 00000000000..a47e91cd628 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/compare/basic.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Checking a typical case (nothing undefined, no NaNs, does not throw, etc.) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, dt1), + 0, + "equal" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, dt2), + -1, + "smaller/larger" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt2, dt1), + 1, + "larger/smaller" +); diff --git a/test/built-ins/Temporal/PlainDateTime/compare/cast.js b/test/built-ins/Temporal/PlainDateTime/compare/cast.js new file mode 100644 index 00000000000..a9a09dc09ad --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/compare/cast.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.compare +description: Arguments may be casted (string, plain object) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + Temporal.PlainDateTime.compare({ year: 1976, month: 11, day: 18, hour: 15 }, dt2), + -1, + "casts first argument (plain object)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare("1976-11-18T15:23:30.123456789", dt2), + -1, + "casts first argument (string)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, { year: 2019, month: 10, day: 29, hour: 10 }), + -1, + "casts second argument (plain object)" +); + +assert.sameValue( + Temporal.PlainDateTime.compare(dt1, "2019-10-29T10:46:38.271986102"), + -1, + "casts second argument (string)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/constructor-full.js b/test/built-ins/Temporal/PlainDateTime/constructor-full.js new file mode 100644 index 00000000000..8715f22122f --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/constructor-full.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Checking an explicitly constructed instance with all arguments +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); + +TemporalHelpers.assertPlainDateTime(datetime, + 1976, 11, "M11", 18, 15, 23, 30, 123, 456, 789, + "check instance (all arguments supplied)" +); + +assert.sameValue( + datetime.calendar, + calendar, + "calendar supplied in constructor can be extracted and is unchanged" +); diff --git a/test/built-ins/Temporal/PlainDateTime/datetime-math.js b/test/built-ins/Temporal/PlainDateTime/datetime-math.js new file mode 100644 index 00000000000..0f2e05c6948 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/datetime-math.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime +description: Testing combinations of since, until, add, subtract, and negated +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const earlier = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const units = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"]; + +units.forEach((largestUnit) => { + const diff = later.since(earlier, { largestUnit }); + TemporalHelpers.assertDurationsEqual( + earlier.since(later, { largestUnit }), + diff.negated(), + `(${earlier}).since(${later}) == (${later}).since(${earlier}).negated()` + ); + TemporalHelpers.assertDurationsEqual( + earlier.until(later, { largestUnit }), + diff, + `(${earlier}).until(${later}) == (${later}).since(${earlier})` + ); + assert.sameValue( + earlier.add(diff).equals(later), + true, + `(${earlier}).add(${diff}) == (${later})` + ); + assert.sameValue( + later.subtract(diff).equals(earlier), + true, + `(${later}).subtract(${diff}) == (${earlier})` + ); + assert.sameValue( + earlier.subtract(diff.negated()).equals(later), + true, + "symmetrical with regard to negative durations (1)" + ); + assert.sameValue( + later.add(diff.negated()).equals(earlier), + true, + "symmetrical with regard to negative durations (2)" + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js index 41673499f72..1786ed59049 100644 --- a/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js @@ -31,6 +31,14 @@ const validValues = [ { 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" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainDateTime/hour-undefined.js b/test/built-ins/Temporal/PlainDateTime/hour-undefined.js index e42831dcd6f..a27c964d1c1 100644 --- a/test/built-ins/Temporal/PlainDateTime/hour-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/hour-undefined.js @@ -5,12 +5,19 @@ esid: sec-temporal.plaindatetime description: Hour argument defaults to 0 if not given features: [Temporal] +includes: [temporalHelpers.js] ---*/ const args = [2000, 5, 2]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.hour, 0, "hour default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, + "hour default argument (argument present)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.hour, 0, "hour default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 0, 0, 0, 0, 0, 0, + "hour default argument (argument missing)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js index 83004a31301..e2fd092f4ac 100644 --- a/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/microsecond-undefined.js @@ -5,12 +5,20 @@ esid: sec-temporal.plaindatetime description: Microsecond argument defaults to 0 if not given features: [Temporal] +includes: [temporalHelpers.js] ---*/ const args = [2000, 5, 2, 12, 34, 56, 123]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.microsecond, 0, "microsecond default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0, + "microsecond default argument (argument present)" +); + +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 123, 0, 0, + "microsecond default argument (argument missing)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.microsecond, 0, "microsecond default argument"); diff --git a/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js index de0c1b84476..33c2a7ec638 100644 --- a/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/millisecond-undefined.js @@ -5,12 +5,19 @@ esid: sec-temporal.plaindatetime description: Millisecond argument defaults to 0 if not given features: [Temporal] +includes: [temporalHelpers.js] ---*/ const args = [2000, 5, 2, 12, 34, 56]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.millisecond, 0, "millisecond default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, + "millisecond default argument (argument present)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.millisecond, 0, "millisecond default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 0, 0, 0, + "millisecond default argument (argument missing)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/minute-undefined.js b/test/built-ins/Temporal/PlainDateTime/minute-undefined.js index 9ac682fc958..8792608e822 100644 --- a/test/built-ins/Temporal/PlainDateTime/minute-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/minute-undefined.js @@ -5,12 +5,19 @@ esid: sec-temporal.plaindatetime description: Minute argument defaults to 0 if not given features: [Temporal] +includes: [temporalHelpers.js] ---*/ const args = [2000, 5, 2, 12]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.minute, 0, "minute default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, + "minute default argument (argument present)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.minute, 0, "minute default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 0, 0, 0, 0, 0, + "minute default argument (argument missing)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js b/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js index f3f8b52c5d4..a913a005ad3 100644 --- a/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/nanosecond-undefined.js @@ -5,12 +5,19 @@ esid: sec-temporal.plaindatetime description: Nanosecond argument defaults to 0 if not given features: [Temporal] +includes: [temporalHelpers.js] ---*/ const args = [2000, 5, 2, 12, 34, 56, 123, 456]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.nanosecond, 0, "nanosecond default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0, + "nanosecond default argument (argument present)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.nanosecond, 0, "nanosecond default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 56, 123, 456, 0, + "nanosecond default argument (argument missing)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js new file mode 100644 index 00000000000..476129400d3 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/ambiguous-date.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Ambiguous addition is handled according to the overflow option +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options not supplied)" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options supplied)" +); + +assert.throws( + RangeError, + () => jan31.add({ months: 1 }, { overflow: "reject" }), + "throw when ambiguous result with reject" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js new file mode 100644 index 00000000000..7fd1317644d --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-duration.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Duration object arguments are handled +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add(Temporal.Duration.from("P1MT1S")), + 2020, 2, "M02", 29, 15, 0, 1, 0, 0, 0, + "Duration argument" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js new file mode 100644 index 00000000000..4780d5ac08f --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-object-insufficient-data.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: At least one recognized property has to be present in argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +assert.throws( + TypeError, + () => jan31.add({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => jan31.add({ month: 12 }), // should be "months" + "misspelled property in argument throws if no other properties are present" +); + +assert.throws( + TypeError, + () => jan31.add({ nonsense: true }), + "unrecognized properties throw if no other recognized property is present" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ nonsense: 1, days: 1 }), + 2020, 2, "M02", 1, 15, 0, 0, 0, 0, 0, + "unrecognized properties ignored provided at least one recognized property is present" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js new file mode 100644 index 00000000000..0a308a79a04 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/argument-plain-object-mixed-signs.js @@ -0,0 +1,18 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +["constrain", "reject"].forEach((overflow) => { + assert.throws( + RangeError, + () => jan31.add({ hours: 1, minutes: -30 }, { overflow }), + `mixed positive and negative values always throw (overflow = "${overflow}")` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js new file mode 100644 index 00000000000..fe6f83e3f6d --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/hour-overflow.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Testing overflow hours (adding hours that push one to the next/previous day) +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const earlier = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + earlier.add({ hours: 2 }), + 2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102, + "hours overflow (push to next day)" +); + +const later = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + later.add({ hours: -12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "hours overflow (push to previous day)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js new file mode 100644 index 00000000000..c60f871e613 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/negative-duration.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Negative durations can be supplied +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ minutes: -30 }), + 2020, 1, "M01", 31, 14, 30, 0, 0, 0, 0, + "negative minutes" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ seconds: -30 }), + 2020, 1, "M01", 31, 14, 59, 30, 0, 0, 0, + "negative seconds" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js new file mode 100644 index 00000000000..d7c923f6f24 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-empty.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, {}), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + jan31.add({ months: 1 }, () => {}), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "options may be function object" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js new file mode 100644 index 00000000000..9255c7a10f4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-invalid.js @@ -0,0 +1,20 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: Various invalid (wrong type) values for options argument +features: [Temporal, Symbol] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => jan31.add({ years: 1 }, bad), + `invalid options (${typeof bad})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js index 2ff326b8d67..6ce6ecc29de 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js @@ -20,4 +20,13 @@ features: [Temporal] 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" })); + + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.add({ months: 1 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js new file mode 100644 index 00000000000..437ac74b60e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfWeek/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofweek +description: Checking day of week for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.dayOfWeek, 4, "check day of week information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js new file mode 100644 index 00000000000..98ee0fbef0a --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/dayOfYear/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.dayofyear +description: Checking day of year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.dayOfYear, 323, "check day of year information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js new file mode 100644 index 00000000000..7059e7a0cb9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInMonth/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinmonth +description: Checking days in month for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInMonth, 30, "check days in month information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js new file mode 100644 index 00000000000..f34e00f7560 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInWeek/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinweek +description: Checking days in week for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInWeek, 7, "check days in week information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js new file mode 100644 index 00000000000..d3c7a5d8a94 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/daysInYear/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.daysinyear +description: Checking days in year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.daysInYear, 366, "check days in year information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js new file mode 100644 index 00000000000..054e032ded5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/argument-object-insufficient-data.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: If argument is an object, it must contain sufficient information +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.throws( + TypeError, + () => dt.equals({ year: 1976 }), + "object must contain required properties" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js new file mode 100644 index 00000000000..c83cffeef4e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Checking a typical case (everything defined, no NaNs, nothing throws, etc.) +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue(dt1.equals(dt1), true, "equal"); +assert.sameValue(dt1.equals(dt2), false, "unequal"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js new file mode 100644 index 00000000000..bad87ec1d7b --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/cast.js @@ -0,0 +1,46 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Argument may be cast +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); + +assert.sameValue( + dt1.equals({ + year: 1976, + month: 11, + day: 18, + hour: 15, + minute: 23, + second: 30, + millisecond: 123, + microsecond: 456, + nanosecond: 789 + }), + true, + "casts argument (plain object, positive)" +); + + +assert.sameValue( + dt2.equals({ year: 1976, month: 11, day: 18, hour: 15 }), + false, + "casts argument (plain object, negative)" +); + +assert.sameValue( + dt1.equals("1976-11-18T15:23:30.123456789"), + true, + "casts argument (string, positive)" +); + +assert.sameValue( + dt2.equals("1976-11-18T15:23:30.123456789"), + false, + "casts argument (string, negative)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js new file mode 100644 index 00000000000..f918a25355e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/monthsInYear/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.monthsinyear +description: Checking months in year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.monthsInYear, 12, "check months in year information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js index 00a3140c539..1a231aad4c7 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js index 59b1314d566..52f4b8fe3bf 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js new file mode 100644 index 00000000000..f6fe8738aec --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/ambiguous-date.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Ambiguous subtraction is handled according to the overflow option +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const mar31 = new Temporal.PlainDateTime(2020, 3, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + mar31.subtract({ months: 1 }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options not supplied)" +); + +TemporalHelpers.assertPlainDateTime( + mar31.subtract({ months: 1 }, { overflow: "constrain" }), + 2020, 2, "M02", 29, 15, 0, 0, 0, 0, 0, + "constrain when ambiguous result (overflow options supplied)" +); + +assert.throws( + RangeError, + () => mar31.subtract({ months: 1 }, { overflow: "reject" }), + "throw when ambiguous result with reject" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js new file mode 100644 index 00000000000..fb0d3d1f8e5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-duration.js @@ -0,0 +1,18 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Duration object arguments are handled +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const subtractWithDuration = jan31.subtract(new Temporal.Duration(0, 1, 0, 0, 0, 1)); +TemporalHelpers.assertPlainDateTime( + subtractWithDuration, + 2019, 12, "M12", 31, 14, 59, 0, 0, 0, 0, + "Duration argument" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js new file mode 100644 index 00000000000..450d14cefef --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-object-insufficient-data.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: At least one recognized property has to be present in argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +assert.throws( + TypeError, + () => jan31.subtract({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => jan31.subtract({ month: 12 }), // should be "months" + "misspelled property in argument throws if no other properties are present" +); + +assert.throws( + TypeError, + () => jan31.subtract({ nonsense: true }), + "unrecognized properties throw if no other recognized property is present" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ nonsense: 1, days: 1 }), + 2020, 1, "M01", 30, 15, 0, 0, 0, 0, 0, + "unrecognized properties ignored provided at least one recognized property is present" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js new file mode 100644 index 00000000000..cabfd209396 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/argument-plain-object-mixed-signs.js @@ -0,0 +1,18 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +["constrain", "reject"].forEach((overflow) => { + assert.throws( + RangeError, + () => jan31.subtract({ hours: 1, minutes: -30 }, { overflow }), + `mixed positive and negative values always throw (overflow = "${overflow}")` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js new file mode 100644 index 00000000000..bda7309920c --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/hour-overflow.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Testing overflow hours (subtracting hours that push one to the next/previous day) +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const later = new Temporal.PlainDateTime(2020, 5, 31, 23, 12, 38, 271, 986, 102); + +TemporalHelpers.assertPlainDateTime( + dt.subtract({ hours: 12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "subtract result" +); + +TemporalHelpers.assertPlainDateTime( + dt.add({ hours: -12 }), + 2019, 10, "M10", 28, 22, 46, 38, 271, 986, 102, + "hour overflow (pushes to previous day)" +); + +TemporalHelpers.assertPlainDateTime( + later.subtract({ hours: -2 }), + 2020, 6, "M06", 1, 1, 12, 38, 271, 986, 102, + "subtracting a negative amount of hours is equivalent to adding hours" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js new file mode 100644 index 00000000000..672d87d9fc4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/negative-duration.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Negative durations can be supplied +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ minutes: -30 }), + 2020, 1, "M01", 31, 15, 30, 0, 0, 0, 0, + "negative minutes" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ seconds: -30 }), + 2020, 1, "M01", 31, 15, 0, 30, 0, 0, 0, + "negative seconds" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js new file mode 100644 index 00000000000..ca9fd5112a8 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-empty.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ months: 2 }, {}), + 2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + jan31.subtract({ months: 2 }, () => {}), + 2019, 11, "M11", 30, 15, 0, 0, 0, 0, 0, + "options may be function object" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js new file mode 100644 index 00000000000..ad8b1244e59 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-invalid.js @@ -0,0 +1,20 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: Various invalid (wrong type) values for options argument +features: [Temporal, Symbol] +---*/ + +const jan31 = new Temporal.PlainDateTime(2020, 1, 31, 15, 0); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => jan31.subtract({ years: 1 }, bad), + `invalid options (${typeof bad})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js index 1e1f1761c81..c3e4b694f44 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] 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" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js new file mode 100644 index 00000000000..5e5b7596a46 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/basic.js @@ -0,0 +1,13 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Checking the string form of an explicitly constructed instance with all arguments +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); + +assert.sameValue(datetime.toString(), "1976-11-18T15:23:30.123456789", "check string value"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js index 3a3c9af8e8f..bc2e1e2c4a8 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js new file mode 100644 index 00000000000..979759ddf67 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/casts-argument.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: String and object arguments get cast +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertDuration( + datetime.until({ year: 2019, month: 10, day: 29, hour: 10 }), + 0, 0, 0, 15684, 18, 36, 29, 876, 543, 211, + "plain object argument" +); + +TemporalHelpers.assertDuration( + datetime.until("2019-10-29T10:46:38.271986102"), + 0, 0, 0, 15684, 19, 23, 8, 148, 529, 313, + "string argument gets cast" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js new file mode 100644 index 00000000000..9a8e31791c0 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/different-calendars-throws.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Using different calendars is not acceptable +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0); + +const cal = { + id: 'thisisnotiso' +}; + +const dt2 = new Temporal.PlainDateTime(2000, 1, 1, 0, 0, 0, 0, 0, 0, cal); + +assert.throws( + RangeError, + () => dt1.until(dt2), + "cannot use until with PDTs having different calendars" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js new file mode 100644 index 00000000000..026024e3100 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/inverse.js @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: The since and until operations act as inverses +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const later = new Temporal.PlainDateTime(2016, 3, 3, 18); + +TemporalHelpers.assertDurationsEqual(dt.until(later), later.since(dt), "until and since act as inverses"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js new file mode 100644 index 00000000000..d064e8246a9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Do not return Durations with unnecessary units +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const lastFeb20 = new Temporal.PlainDateTime(2020, 2, 29, 0, 0); +const lastFeb21 = new Temporal.PlainDateTime(2021, 2, 28, 0, 0); + +TemporalHelpers.assertDuration( + lastFeb20.until(lastFeb21, { largestUnit: "months" }), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + "does not include higher units than necessary (largest unit = months)" +); + +TemporalHelpers.assertDuration( + lastFeb20.until(lastFeb21, { largestUnit: "years" }), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "does not include higher units than necessary (largest unit = years)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js new file mode 100644 index 00000000000..b6e00ead5d5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/returns-days.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Return days by default +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); +const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "auto" }), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, + "defaults to returning days (largest unit = auto)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "days" }), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 0, + "defaults to returning days (largest unit = days)" +); + +TemporalHelpers.assertDuration( + feb20.until(new Temporal.PlainDateTime(2021, 2, 1, 0, 0, 0, 0, 0, 1)), + 0, 0, 0, 366, 0, 0, 0, 0, 0, 1, + "returns nanoseconds if argument is PDT with non-zero nanoseconds" +); + +const dt = new Temporal.PlainDateTime(2020, 2, 1, 0, 0, 0, 0, 0, 1); + +TemporalHelpers.assertDuration( + dt.until(feb21), + 0, 0, 0, 365, 23, 59, 59, 999, 999, 999, + "one nanosecond away from one year away" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js index f907ababfd0..47455e7a191 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js new file mode 100644 index 00000000000..d731a2111f6 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/subseconds.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Largest unit is respected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); + +const later = feb20.add({ + days: 1, + milliseconds: 250, + microseconds: 250, + nanoseconds: 250 +}); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, 86400250, 250, 250, + "can return subseconds (millisecond precision)" +); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 86400250250, 250, + "can return subseconds (microsecond precision)" +); + +TemporalHelpers.assertDuration( + feb20.until(later, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 86400250250250, + "can return subseconds (nanosecond precision)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js new file mode 100644 index 00000000000..f13fcb1834e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js @@ -0,0 +1,66 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Largest unit is respected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); +const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "years" }), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (years)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "months" }), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (months)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "weeks" }), + 0, 0, 52, 2, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (weeks)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "hours" }), + 0, 0, 0, 0, 8784, 0, 0,0, 0, 0, + "can return lower or higher units (hours)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "minutes" }), + 0, 0, 0, 0, 0, 527040, 0, 0, 0, 0, 0, + "can return lower or higher units (minutes)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "seconds" }), + 0, 0, 0, 0, 0, 0, 31622400, 0, 0, 0, + "can return lower or higher units (seconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, 31622400000, 0, 0, + "can return lower or higher units (milliseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000, 0, + "can return lower or higher units (microseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000000, + "can return lower or higher units (nanoseconds)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js new file mode 100644 index 00000000000..06d8e2b706f --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Weeks and months are mutually exclusive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const laterDateTime = dt.add({ days: 42, hours: 3 }); + +TemporalHelpers.assertDuration( + dt.until(laterDateTime, { largestUnit: "weeks" }), + 0, 0, 6, 0, 3, 0, 0, 0, 0, 0, + "weeks and months mutually exclusive (1)" +); + +TemporalHelpers.assertDuration( + dt.until(laterDateTime, { largestUnit: "months" }), + 0, 1, 0, 12, 3, 0, 0, 0, 0, 0, + "weeks and months mutually exclusive (2)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js new file mode 100644 index 00000000000..3da2878448e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/valueOf/basic.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.valueof +description: Comparison operators (except !== and ===) do not work +features: [Temporal] +---*/ + +const dt1 = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789); +const dt1again = new Temporal.PlainDateTime(1963, 2, 13, 9, 36, 29, 123, 456, 789); +const dt2 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.sameValue(dt1 === dt1, true, "object equality implies ==="); +assert.sameValue(dt1 !== dt1again, true, "object non-equality, even if all data is the same, implies !=="); +assert.throws(TypeError, () => dt1 < dt1, "< throws (same objects)"); +assert.throws(TypeError, () => dt1 < dt2, "< throws (different objects)"); +assert.throws(TypeError, () => dt1 > dt1, "> throws (same objects)"); +assert.throws(TypeError, () => dt1 > dt2, "> throws (different objects)"); +assert.throws(TypeError, () => dt1 <= dt1, "<= does not throw (same objects)"); +assert.throws(TypeError, () => dt1 <= dt2, "<= throws (different objects)"); +assert.throws(TypeError, () => dt1 >= dt1, ">= throws (same objects)"); +assert.throws(TypeError, () => dt1 >= dt2, ">= throws (different objects)"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js new file mode 100644 index 00000000000..6273dbc54cd --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/weekOfYear/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.weekofyear +description: Checking week of year for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.weekOfYear, 47, "check week of year information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js new file mode 100644 index 00000000000..5c4c4e2b5bf --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-object-insufficient-data.js @@ -0,0 +1,42 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Unrecognized properties (incl. plurals of recognized units) are ignored +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +assert.throws( + TypeError, + () => instance.with({}), + "empty object not acceptable" +); + +const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; + +units.forEach((unit) => { + let plural = `${unit}s`; + let options = {}; + options[plural] = 1; + assert.throws( + TypeError, + () => instance.with(options), + `plural unit ("${plural}" vs "${unit}") is not acceptable` + ); +}); + +assert.throws( + TypeError, + () => instance.with({nonsense: true}), + "throw if no recognized properties present" +); + +TemporalHelpers.assertPlainDateTime( + instance.with({year: 1965, nonsense: true}), + 1965, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + "unrecognized properties ignored & does not throw if recognized properties present)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js new file mode 100644 index 00000000000..d021389adcf --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/basic.js @@ -0,0 +1,77 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: A variety of "normal" (non-throwing, non-boundary case, non-null, etc.) arguments +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ year: 2019 }), + 2019, 11, "M11", 18, 15, 23, 30, 123, 456, 789, + "with year works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ month: 5 }), + 1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789, + "with month works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ monthCode: "M05" }), + 1976, 5, "M05", 18, 15, 23, 30, 123, 456, 789, + "with month code works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 5 }), + 1976, 11, "M11", 5, 15, 23, 30, 123, 456, 789, + "with day works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ hour: 5 }), + 1976, 11, "M11", 18, 5, 23, 30, 123, 456, 789, + "with hour works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ minute: 5 }), + 1976, 11, "M11", 18, 15, 5, 30, 123, 456, 789, + "with minute works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ second: 5 }), + 1976, 11, "M11", 18, 15, 23, 5, 123, 456, 789, + "with second works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ millisecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 5, 456, 789, + "with millisecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ microsecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 123, 5, 789, + "with microsecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ nanosecond: 5 }), + 1976, 11, "M11", 18, 15, 23, 30, 123, 456, 5, + "with nanosecond works" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ month: 5, second: 15 }), + 1976, 5, "M05", 18, 15, 23, 15, 123, 456, 789, + "with month and second works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js new file mode 100644 index 00000000000..165c7b57b2a --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-throws.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a calendar is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => datetime.with({ year: 2021, calendar: "iso8601" }), + "throws with calendar property" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js new file mode 100644 index 00000000000..6e81bac840e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/month-and-monthcode-must-agree.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: The month and month code should agree +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + RangeError, + () => datetime.with({ month: 5, monthCode: "M06" }), + "month and monthCode must agree" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js new file mode 100644 index 00000000000..5a5309f2e20 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/multiple-unrecognized-properties-ignored.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Unrecognized units are ignored +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); +const units = ["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; + +units.forEach((unit) => { + let plural = `${unit}s`; + let arg = { month: 12 }; + arg[plural] = 1; + TemporalHelpers.assertPlainDateTime( + datetime.with(arg), + 1976, 12, "M12", 18, 15, 23, 30, 123, 456, 789, + `unrecognized property (${plural}) gets ignored` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js new file mode 100644 index 00000000000..3bc92e0d8e6 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-empty.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 40 }, {}), + 1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789, + "options may be empty object" +); + +TemporalHelpers.assertPlainDateTime( + datetime.with({ day: 40 }, () => {}), + 1976, 11, "M11", 30, 15, 23, 30, 123, 456, 789, + "read empty options from function object" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js new file mode 100644 index 00000000000..8f52de349e6 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-invalid.js @@ -0,0 +1,20 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Verify that undefined options are handled correctly. +features: [Temporal, Symbol] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +const badOptions = [null, 1, 'hello', true, Symbol('foo'), 1n]; + +badOptions.forEach((bad) => { + assert.throws( + TypeError, + () => datetime.with({ day: 5 }, bad), + `bad options (${typeof bad})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js index 9e3f5617846..4d3b05b0eac 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js @@ -18,4 +18,12 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); -assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js new file mode 100644 index 00000000000..405a12fadbe --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/string-throws.js @@ -0,0 +1,20 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a string argument is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + +const baddies = ["12:00", "1995-04-07", "2019-05-17T12:34:56.007007007", "2019-05-17T12:34:56.007007007Z", "42"]; + +baddies.forEach((bad) => { + assert.throws( + TypeError, + () => instance.with(bad), + `bad argument (${bad})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js new file mode 100644 index 00000000000..0931204b16f --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/timezone-throws.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if a timezone is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => datetime.with({ year: 2021, timeZone: "UTC" }), + "throws with timezone property" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js new file mode 100644 index 00000000000..0ddb21932d1 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Unrecognized properties of plain object ignored +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +assert.throws( + TypeError, + () => dt.withPlainDate({}), + "empty object not acceptable" +); + +assert.throws( + TypeError, + () => dt.withPlainDate({ months: 12 }), // should be "month" + "no recognized properties (look like it might work)" +); + +assert.throws( + TypeError, + () => dt.with({nonsense: true}), + "no recognized properties (clearly won't work)" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate({ year: 2000, month: 6, day: 1, months: 123 }), // 'months' unrecognized; see above + 2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0, + "unrecognized properties ignored & does not throw if recognized properties present)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js new file mode 100644 index 00000000000..b7e336344aa --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Plain object may be acceptable +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate({ year: 2000, month: 6, day: 1 }), + 2000, 6, "M06", 1, 3, 24, 30, 0, 0, 0, + "plain object works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js new file mode 100644 index 00000000000..14ebb69c035 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate.js @@ -0,0 +1,18 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate object is acceptable +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); +const date = new Temporal.PlainDate(2020, 1, 23); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate(date), + 2020, 1, "M01", 23, 3, 24, 30, 0, 0, 0, + "PlainDate argument works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 00000000000..a4f4d9350f0 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js new file mode 100644 index 00000000000..f3349a95df5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: New calendar is preserved if original PDT has ISO calendar +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const cal = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { return "this is a string"; }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); +const shifted = dt.withPlainDate("2010-11-12"); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is unchanged if input has ISO calendar (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal, + "calendar is unchanged if input has ISO calendar (2)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js new file mode 100644 index 00000000000..902cae34dc0 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate-like string argument is acceptable +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainDate("2018-09-15"), + 2018, 9, "M09", 15, 3, 24, 30, 0, 0, 0, + "PlainDate-like string argument works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js new file mode 100644 index 00000000000..505df4d3b58 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/non-compatible-calendars-throw.js @@ -0,0 +1,28 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.withplaindate +description: If two non-ISO calendars are involved, an error is raised +features: [Temporal] +---*/ + +const cal = { + id: 'foo', + toString() { return "this is a string"; }, +}; + +const dt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); + +const anotherCal = { + id: 'bar', + toString() { return "this is another string"; }, +}; + +const date = new Temporal.PlainDate(2008, 9, 6, anotherCal); + +assert.throws( + RangeError, + () => dt.withPlainDate(date), + "throws if both `this` and `other` have a non-ISO calendar" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js new file mode 100644 index 00000000000..3143b43c5e8 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-object-insufficient-data.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: A plain object can be used as an argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +assert.throws( + TypeError, + () => dt.withPlainTime({}), + "empty object not an acceptable argument" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime({ hour: 10 }), + 2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0, + "plain object (hour) works" +); + +assert.throws( + TypeError, + () => dt.withPlainTime({ hours: 9 }), // should be "hour", see above + "plain object with a single unrecognized property fails" +); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime({ hour: 10, seconds: 123 }), + 2015, 12, "M12", 7, 10, 0, 0, 0, 0, 0, + "unrecognized properties are ignored if at least one recognized property is present" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js new file mode 100644 index 00000000000..2acd0c8a3ac --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-string-without-time-designator.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: String argument without ISO 8601 time designator "T" allowed +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime("12:34"), + 2015, 12, "M12", 7, 12, 34, 0, 0, 0, 0, + "time-like string works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js new file mode 100644 index 00000000000..885116f7d06 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-time.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: An instance of PlainTime can be used as an argument +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); +const hour = 11; +const minute = 22; +const time = new Temporal.PlainTime(hour, minute); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime(time), + 2015, + 12, + "M12", + 7, + hour, + minute, + 0, + 0, + 0, + 0, + "PlainTime argument works" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js new file mode 100644 index 00000000000..bcda293fb20 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainTime/no-argument-default-to-midnight.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaintime +description: If no argument is given, default to midnight +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(2015, 12, 7, 3, 24, 30, 0, 3, 500); + +TemporalHelpers.assertPlainDateTime( + dt.withPlainTime(), + 2015, 12, "M12", 7, 0, 0, 0, 0, 0, 0, + "no argument defaults to midnight" +); diff --git a/test/built-ins/Temporal/PlainDateTime/second-undefined.js b/test/built-ins/Temporal/PlainDateTime/second-undefined.js index 9ec2ea3ef79..4b8422d4c35 100644 --- a/test/built-ins/Temporal/PlainDateTime/second-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/second-undefined.js @@ -4,13 +4,20 @@ /*--- esid: sec-temporal.plaindatetime description: Second argument defaults to 0 if not given +includes: [temporalHelpers.js] features: [Temporal] ---*/ const args = [2000, 5, 2, 12, 34]; -const explicit = new Temporal.PlainDateTime(...args, undefined); -assert.sameValue(explicit.second, 0, "second default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args, undefined), + 2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0, + "second default argument (argument present)" +); -const implicit = new Temporal.PlainDateTime(...args); -assert.sameValue(implicit.second, 0, "second default argument"); +TemporalHelpers.assertPlainDateTime( + new Temporal.PlainDateTime(...args), + 2000, 5, "M05", 2, 12, 34, 0, 0, 0, 0, + "second default argument (argument missing)" +); diff --git a/test/built-ins/Temporal/PlainMonthDay/calendar-always.js b/test/built-ins/Temporal/PlainMonthDay/calendar-always.js new file mode 100644 index 00000000000..8b9d87ff0a0 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/calendar-always.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pmd = new Temporal.PlainMonthDay(10, 31, "iso8601", 2019); + +assert.sameValue( + pmd.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPMD = Temporal.PlainMonthDay.from("2019-10-31"); // 2019 will get dropped + +assert.sameValue( + anotherPMD.toString({ calendarName: 'always' }), + "1972-10-31[u-ca=iso8601]", + "emit fallback year if calendarName = 'always' (static from)" +); diff --git a/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js index c2427006fdc..48ccf843643 100644 --- a/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js @@ -27,6 +27,14 @@ const validValues = [ { monthCode: "M05", day: 2 }, "05-02", ]; -validValues.forEach((value) => { - assert.throws(RangeError, () => Temporal.PlainMonthDay.from(value, { overflow: "other string" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainMonthDay.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js index fadff8929f4..4d1d85b6797 100644 --- a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js @@ -8,9 +8,9 @@ features: [Temporal] ---*/ const tests = [ - [[], "05-02[u-ca=iso8601]"], + [[], "1972-05-02[u-ca=iso8601]"], [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], - [[{ toString() { return "iso8601"; } }], "05-02[u-ca=iso8601]"], + [[{ toString() { return "iso8601"; } }], "1972-05-02[u-ca=iso8601]"], [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i ]; diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js index 5ed47e97538..0036dfe6380 100644 --- a/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const monthday = new Temporal.PlainMonthDay(5, 2); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => monthday.with({ day: 8 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => monthday.with({ day: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainTime/from/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js similarity index 100% rename from test/built-ins/Temporal/PlainTime/from/argument-string-invalid.js rename to test/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js diff --git a/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js index 856d071453e..dcefde8a682 100644 --- a/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js @@ -19,8 +19,14 @@ const validValues = [ { hour: 12 }, "12:00", ]; -validValues.forEach((value) => { - ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"].forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainTime.from(value, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js index 200c100d2e8..ba3fa48a7e0 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js @@ -8,6 +8,6 @@ features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); -for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l"]) { +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { assert.throws(RangeError, () => time.round({ smallestUnit: "microsecond", roundingMode })); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js index 6dc1b1ab6ee..623d9463714 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js @@ -9,7 +9,6 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); - -for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto"]) { +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js new file mode 100644 index 00000000000..768f1dba079 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js index 529541f2ad9..c66d624740c 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js @@ -8,6 +8,6 @@ features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); -for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l"]) { +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { assert.throws(RangeError, () => time.toString({ smallestUnit: "microsecond", roundingMode })); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js new file mode 100644 index 00000000000..03b196269e8 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg }), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js index e9fbe3b9c04..1b2aa526d12 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js @@ -9,7 +9,6 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); - -for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto"]) { +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js index 796cec5fcf3..dc50e7795bc 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js @@ -16,6 +16,12 @@ features: [Temporal] const time = new Temporal.PlainTime(12); const values = ["", "CONSTRAIN", "balance", "other string"]; -for (const overflow of values) { - assert.throws(RangeError, () => time.with({ minute: 45 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => time.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/calendar-always.js b/test/built-ins/Temporal/PlainYearMonth/calendar-always.js new file mode 100644 index 00000000000..0aad58df09f --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/calendar-always.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pym = new Temporal.PlainYearMonth(2019, 10, "iso8601", 31); + +assert.sameValue( + pym.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPYM = Temporal.PlainYearMonth.from("2019-10-31"); // 31 will get dropped + +assert.sameValue( + anotherPYM.toString({ calendarName: 'always' }), + "2019-10-01[u-ca=iso8601]", + "emit fallback day if calendarName = 'always' (static from)" +); diff --git a/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js index d30774eece5..11335f2481a 100644 --- a/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js @@ -27,8 +27,14 @@ const validValues = [ { year: 2000, month: 5 }, "2000-05", ]; -validValues.forEach((value) => { - ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"].forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainYearMonth.from(value, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js index 4913de46a29..1633f1b6544 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js @@ -20,6 +20,12 @@ features: [Temporal] const yearmonth = new Temporal.PlainYearMonth(2000, 5); const duration = new Temporal.Duration(1, 1); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.add(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js index 14cbe1ac2fb..ae3e9de8e34 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js index 8c2efb855a7..46286d5a6a2 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js @@ -20,6 +20,12 @@ features: [Temporal] const yearmonth = new Temporal.PlainYearMonth(2000, 5); const duration = new Temporal.Duration(1, 1); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js index d6fa52e1064..be8cc7e93f8 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js @@ -14,7 +14,7 @@ const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); [ - [yearmonth1, "2000-05[u-ca=iso8601]"], + [yearmonth1, "2000-05-01[u-ca=iso8601]"], // fallback day 1 used [yearmonth2, "2000-05-01[u-ca=custom]"], ].forEach(([yearmonth, expected]) => { const result = yearmonth.toString({ calendarName: "always" }); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js index 3e6231aef4c..d5f8d9884f2 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js index 587c66754c8..4684d597f3e 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const yearmonth = new Temporal.PlainYearMonth(2000, 5); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.with({ month: 8 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js index 5913d3e7f96..e8406c57e37 100644 --- a/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js @@ -32,6 +32,14 @@ const validValues = [ { 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" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.ZonedDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js index 4c88b568784..ede72ad4a96 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] 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" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js index 145e3f615a7..b5b58bc40d6 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/round/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); -assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.round({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js index 8fd11a6ba56..c749232dcd2 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js index 8c144ef70d0..7a7d4fd1206 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] 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" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js index 01d86acc415..50b223237ca 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-invalid-string.js @@ -8,4 +8,6 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); -assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode: "other string" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js index 70d98276591..3cedb0046df 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingmode-invalid-string.js @@ -9,4 +9,6 @@ features: [Temporal] 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" })); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "expand", "halfCeil", "halfFloor", "halfTrunc", "halfEven", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js index 96d5ab3799d..843437f59fd 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js @@ -18,4 +18,11 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); -assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 00000000000..003bf13f1b8 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js b/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js index 1274a0daac7..e92266498e4 100644 --- a/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js +++ b/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js @@ -1,4 +1,5 @@ // Copyright 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-initializenumberformat @@ -26,14 +27,18 @@ assert.throws(RangeError, function() { new Intl.NumberFormat([], {roundingIncrement: 5001}); }, '5001'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'morePrecision'}); }, '2, roundingType is "morePrecision"'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'lessPrecision'}); }, '2, roundingType is "lessPrecision"'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, minimumSignificantDigits: 1}); }, '2, roundingType is "significantDigits"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, maximumFractionDigits:3 , minimumFractionDigits:2 }); +}, '"maximumFractionDigits" is not equal to "minimumFractionDigits"'); diff --git a/test/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js b/test/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js new file mode 100644 index 00000000000..dcbdeb8266e --- /dev/null +++ b/test/intl402/NumberFormat/prototype/format/format-max-min-fraction-significant-digits.js @@ -0,0 +1,27 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-intl.numberformat.prototype.format +description: Tests that the digits are determined correctly when specifying at same time «"minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"» +features: [Intl.NumberFormat-v3] +includes: [testIntl.js] +---*/ + +var locales = [new Intl.NumberFormat().resolvedOptions().locale, "ar", "de", "th", "ja"]; +var numberingSystems = ["latn", "arab", "thai", "hanidec"]; + +var nfTestMatrix = [ + // mnfd & mxfd > mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }], + [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 1, maximumSignificantDigits: 2 }, { 1.23456: "1.2" }], + // mnfd & mxfd ∩ mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 2, maximumFractionDigits: 4, minimumSignificantDigits: 2, maximumSignificantDigits: 3 }, { 1.23456: "1.23" }], + // mnfd & mxfd < mnsd & mxsd + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 1, maximumSignificantDigits: 4}, { 1.23456: "1.235" }], + [{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2, minimumSignificantDigits: 2, maximumSignificantDigits: 4}, { 1.23456: "1.235" }], +]; + +nfTestMatrix.forEach((nfTestValues)=>{ + testNumberFormat(locales, numberingSystems, ...nfTestValues) +}) diff --git a/test/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js b/test/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js index 9b192d4bd35..45ccd67d84c 100644 --- a/test/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js +++ b/test/intl402/NumberFormat/prototype/formatRange/x-greater-than-y-throws.js @@ -18,7 +18,7 @@ info: | (...) 1.1.21_4.a if y is a mathematical value and y < 0, throw a RangeError exception. 1.1.21_4.b if y is -∞, throw a RangeError exception. - features: [Intl.NumberFormat-v3] +features: [Intl.NumberFormat-v3] ---*/ const nf = new Intl.NumberFormat(); diff --git a/test/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js b/test/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js index 719f1bee004..ab264b92e6d 100644 --- a/test/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js +++ b/test/intl402/NumberFormat/prototype/formatRangeToParts/x-greater-than-y-throws.js @@ -18,7 +18,7 @@ info: | (...) 1.1.21_4.a if y is a mathematical value and y < 0, throw a RangeError exception. 1.1.21_4.b if y is -∞, throw a RangeError exception. - features: [Intl.NumberFormat-v3] +features: [Intl.NumberFormat-v3] ---*/ const nf = new Intl.NumberFormat(); diff --git a/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js b/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js new file mode 100644 index 00000000000..b7a6b5c0bc1 --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.era(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js b/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js new file mode 100644 index 00000000000..6b3f65b9ea4 --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.eraYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/intl402/Temporal/TimeZone/etc-timezone.js b/test/intl402/Temporal/TimeZone/etc-timezone.js new file mode 100644 index 00000000000..b3995e5f4ca --- /dev/null +++ b/test/intl402/Temporal/TimeZone/etc-timezone.js @@ -0,0 +1,79 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Some Etc/GMT{+/-}{0}N timezones are valid, but not all +features: [Temporal] +---*/ + +// "Etc/GMT-0" through "Etc/GMT-14" are OK + +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT-0")).toString(), + "UTC", // if the offset is -0, we say "UTC" rather than "GMT" + "Etc/GMT-0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12,13,14].forEach((n) => { + let tz = "Etc/GMT-" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtMinus24TZ = "Etc/GMT-24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtMinus24TZ); }, + gmtMinus24TZ + " is an invalid timezone" +); + +// "Etc/GMT-0N" is not OK (1 ≤ N ≤ 9) +[1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT-0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// "Etc/GMT+0N" is not OK (0 ≤ N ≤ 9) +[0,1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT+0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// Etc/GMT+0" through "Etc/GMT+12" are OK + +// zero is handled in its own way (say "UTC" rather than "GMT"): +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT+0")).toString(), + "UTC", // if the offset is +0, we say "UTC" rather than "GMT" + "Etc/GMT+0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12].forEach((n) => { + let tz = "Etc/GMT+" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtPlus24TZ = "Etc/GMT+24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtPlus24TZ); }, + gmtPlus24TZ + " is an invalid timezone" +);