diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until')
92 files changed, 2815 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..65a50eeeb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-builtin-calendar-no-array-iteration.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calling the method with a property bag argument with a builtin calendar causes + no observable array iteration when getting the calendar fields. +features: [Temporal] +---*/ + +const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function arrayIterator() { + throw new Test262Error("Array should not be iterated"); +} + +const instance = new Temporal.PlainDate(2000, 5, 2); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.until(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..81df965c93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-calendar-datefromfields-called-with-null-prototype-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calendar.dateFromFields method is called with a null-prototype fields object +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution(); +const instance = new Temporal.PlainDate(2000, 5, 2); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.until(arg); +assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..11d0874d9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-constructor-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaindate.prototype.until +description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainDate(2000, 5, 2); + +assert.throws(RangeError, () => instance.until(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..ef00260ae3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-duplicate-calendar-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaindate.prototype.until +description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const extra_fields of [['foo', 'foo'], ['day'], ['month'], ['monthCode'], ['year']]) { + const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields); + const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar }; + const instance = new Temporal.PlainDate(2000, 5, 2); + + assert.throws(RangeError, () => instance.until(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-leap-second.js new file mode 100644 index 0000000000..e62b69de21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-leap-second.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Leap second is a valid ISO string for PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2016, 12, 31); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.until(arg); +TemporalHelpers.assertDuration( + result1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "leap second is a valid ISO string for PlainDate" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.until(arg); +TemporalHelpers.assertDuration( + result2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-number.js new file mode 100644 index 0000000000..c181972581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.until(arg), + 'Numbers cannot be used in place of an ISO string for PlainDate' + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js new file mode 100644 index 0000000000..8dfa1b88ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.until +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const date = new Temporal.PlainDate(2000, 5, 2); + const result = date.until(datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..c3a029272a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: The calendar name is case-insensitive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.until(arg); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..a05da04f05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Leap second is a valid ISO string for a calendar in a property bag +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.until(arg); +TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..c46e6ff2ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.until(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..2dddc518d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-string.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: A calendar ID is valid input for Calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.until(arg); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..65304590aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-wrong-type.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Appropriate error thrown when a calendar property from a property bag cannot + be converted to a calendar object or string +features: [BigInt, Symbol, Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.PlainDate(2000, 5, 2); + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [calendar, description] of primitiveTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws( + typeof calendar === 'string' ? RangeError : TypeError, + () => instance.until(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object that doesn't implement the protocol"], + [new Temporal.TimeZone("UTC"), "time zone instance"], + [Temporal.Calendar, "Temporal.Calendar, object"], + [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields() +]; + +for (const [calendar, description] of typeErrorTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws(TypeError, () => instance.until(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..abe100487e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-propertybag-calendar-year-zero.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T17:45", + "-000000-10-31T17:45Z", + "-000000-10-31T17:45+01:00", + "-000000-10-31T17:45+00:00[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..01c0f901aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-proto-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaindate.prototype.until +description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainDate(2000, 5, 2); + +assert.throws(RangeError, () => instance.until(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..a19cb0caff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-calendar-annotation.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[u-ca=iso8601]", "without time or time zone"], + ["2000-05-02[UTC][u-ca=iso8601]", "with time zone and no time"], + ["2000-05-02T15:23[u-ca=iso8601]", "without time zone"], + ["2000-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"], + ["2000-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"], + ["2000-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["2000-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..ac10df4a67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-critical-unknown-annotation.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..06692bd6b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-date-with-utc-offset.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const validStrings = [ + "2000-05-02T00+00:00", + "2000-05-02T00+00:00[UTC]", + "2000-05-02T00+00:00[!UTC]", + "2000-05-02T00-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `"${arg}" is a valid UTC offset with time for PlainDate` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.until(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js new file mode 100644 index 0000000000..47c10e5c58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..db7f9127f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..1ec82cadc5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-multiple-time-zone.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-separators.js new file mode 100644 index 0000000000..e9c944cc64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-separators.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02T15:23", "uppercase T"], + ["2000-05-02t15:23", "lowercase T"], + ["2000-05-02 15:23", "space between date and time"], +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..f8cdb4306e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-time-zone-annotation.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[Asia/Kolkata]", "named, with no time"], + ["2000-05-02[!Europe/Vienna]", "named, with ! and no time"], + ["2000-05-02[+00:00]", "numeric, with no time"], + ["2000-05-02[!-02:30]", "numeric, with ! and no time"], + ["2000-05-02T15:23[America/Sao_Paulo]", "named, with no offset"], + ["2000-05-02T15:23[!Asia/Tokyo]", "named, with ! and no offset"], + ["2000-05-02T15:23[-02:30]", "numeric, with no offset"], + ["2000-05-02T15:23[!+00:00]", "numeric, with ! and no offset"], + ["2000-05-02T15:23+00:00[America/New_York]", "named, with offset"], + ["2000-05-02T15:23+00:00[!UTC]", "named, with offset and !"], + ["2000-05-02T15:23+00:00[+01:00]", "numeric, with offset"], + ["2000-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"], +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..c8b5af5c6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-unknown-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Various forms of unknown annotation +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[foo=bar]", "without time"], + ["2000-05-02T15:23[foo=bar]", "alone"], + ["2000-05-02T15:23[UTC][foo=bar]", "with time zone"], + ["2000-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"], + ["2000-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["2000-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..95f193aed7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-wrong-type.js new file mode 100644 index 0000000000..d6886c8c7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainDate +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.until(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainDate, "Temporal.PlainDate, object"], + [Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.until(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..807b83051b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-convert.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: An exception from TimeZone#getOffsetNanosecondsFor() is propagated. +features: [Temporal] +---*/ + +class TZ extends Temporal.TimeZone { + constructor() { super("UTC") } + getOffsetNanosecondsFor() { throw new Test262Error() } +} + +const tz = new TZ(); +const arg = new Temporal.ZonedDateTime(0n, tz); +const instance = new Temporal.PlainDate(1976, 11, 18); + +assert.throws(Test262Error, () => instance.until(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..7777ce9c05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-slots.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Getters are not called when converting a ZonedDateTime to a PlainDate. +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.ZonedDateTime.prototype); +const getters = ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "calendar"]; + +for (const property of getters) { + Object.defineProperty(Temporal.ZonedDateTime.prototype, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); +} + +const arg = new Temporal.ZonedDateTime(0n, "UTC"); +const instance = new Temporal.PlainDate(1976, 11, 18); +instance.until(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..cc57645903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..12ee440503 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => date.until(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..31bf9a778f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..5bdc156026 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => date.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js new file mode 100644 index 0000000000..d2166e9e3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/basic.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Basic tests for until(). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(1969, 7, 24); +const plainDate2 = Temporal.PlainDate.from({ year: 1969, month: 10, day: 5 }); +TemporalHelpers.assertDuration(plainDate.until(plainDate2), 0, 0, 0, /* days = */ 73, 0, 0, 0, 0, 0, 0, "same year"); + +const earlier = new Temporal.PlainDate(1969, 7, 24); +const later = new Temporal.PlainDate(1996, 3, 3); +TemporalHelpers.assertDuration(earlier.until(later), 0, 0, 0, /* days = */ 9719, 0, 0, 0, 0, 0, 0, "different year"); + +TemporalHelpers.assertDuration(plainDate.until({ year: 2019, month: 7, day: 24 }), 0, 0, 0, /* days = */ 18262, 0, 0, 0, 0, 0, 0, "option bag"); +TemporalHelpers.assertDuration(plainDate.until("2019-07-24"), 0, 0, 0, /* days = */ 18262, 0, 0, 0, 0, 0, 0, "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/branding.js new file mode 100644 index 0000000000..2625e235f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const until = Temporal.PlainDate.prototype.until; + +assert.sameValue(typeof until, "function"); + +const args = [new Temporal.PlainDate(2022, 6, 22)]; + +assert.throws(TypeError, () => until.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => until.apply(null, args), "null"); +assert.throws(TypeError, () => until.apply(true, args), "true"); +assert.throws(TypeError, () => until.apply("", args), "empty string"); +assert.throws(TypeError, () => until.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => until.apply(1, args), "1"); +assert.throws(TypeError, () => until.apply({}, args), "plain object"); +assert.throws(TypeError, () => until.apply(Temporal.PlainDate, args), "Temporal.PlainDate"); +assert.throws(TypeError, () => until.apply(Temporal.PlainDate.prototype, args), "Temporal.PlainDate.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin-calendar-no-observable-calls.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin-calendar-no-observable-calls.js new file mode 100644 index 0000000000..400f425860 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin-calendar-no-observable-calls.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calling the method on an instance constructed with a builtin calendar causes + no observable lookups or calls to calendar methods. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const dateUntilOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "dateUntil"); +Object.defineProperty(Temporal.Calendar.prototype, "dateUntil", { + configurable: true, + enumerable: false, + get() { + TemporalHelpers.assertUnreachable("dateUntil should not be looked up"); + }, +}); + +const instance = new Temporal.PlainDate(2000, 5, 2, "iso8601"); +instance.until(new Temporal.PlainDate(2001, 6, 13)); + +Object.defineProperty(Temporal.Calendar.prototype, "dateUntil", dateUntilOriginal); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js new file mode 100644 index 0000000000..d65f2e5af7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Tests that Temporal.PlainDate.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainDate.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainDate.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainDate.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainDate.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js new file mode 100644 index 0000000000..6b72eabd28 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + relativeTo parameters that are not ZonedDateTime or undefined, are always + converted to PlainDate for observable calendar calls +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); +const instance = new Temporal.PlainDate(1970, 1, 1, calendar); +calendar.specificPlainDate = instance; +instance.until(new Temporal.PlainDate(2000, 5, 2, calendar), { smallestUnit: "month" }); +assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..c4455c2f1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.until({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js new file mode 100644 index 0000000000..2945cae16d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-null-prototype-options.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Calendar.dateUntil method is called with a null-prototype object as the + options value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarCheckOptionsPrototypePollution(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +const argument = new Temporal.PlainDate(2022, 6, 14, calendar); +instance.until(argument, { largestUnit: "months" }); +assert.sameValue(calendar.dateUntilCallCount, 1, "dateUntil should have been called on the calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js new file mode 100644 index 0000000000..7a7f9d92f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form +info: | + sec-temporal.plaindate.prototype.until steps 12–13: + 13. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_). + 14. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _temporalDate_, _other_, _untilOptions_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( + (calendar, largestUnit) => { + const earlier = new Temporal.PlainDate(2000, 5, 2, calendar); + const later = new Temporal.PlainDate(2001, 6, 3, calendar); + earlier.until(later, { largestUnit }); + }, + { + years: ["year"], + months: ["month"], + weeks: ["week"], + days: [] + } +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js new file mode 100644 index 0000000000..b77217dd0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-fields-iterable.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const date = new Temporal.PlainDate(2000, 5, 2, calendar1); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +date.until({ year: 2005, month: 6, day: 2, calendar: calendar2 }); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar2.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar2.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js new file mode 100644 index 0000000000..ddff8dae6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-id-match.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Calculation is performed if calendars' toString results match +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class Calendar1 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} +class Calendar2 extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + toString() { + return "A"; + } +} + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, new Calendar1()); +const plainDate2 = new Temporal.PlainDate(2000, 1, 2, new Calendar2()); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 1, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js new file mode 100644 index 0000000000..632e9d69e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-invalid-return.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Throw when the returned value from the calendar's dateUntil method is not a Duration. +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor(value) { + super("iso8601"); + this.value = value; + } + dateUntil() { + return this.value; + } +} + +const tests = [ + [undefined], + [null, "null"], + [true], + ["2000-05"], + [Symbol()], + [200005], + [200005n], + [{}, "plain object"], + [() => {}, "lambda"], + [Temporal.Duration, "Temporal.Duration"], + [Temporal.Duration.prototype, "Temporal.Duration.prototype"], +]; +for (const [test, description = typeof test] of tests) { + const plainDate = new Temporal.PlainDate(2000, 5, 2, new CustomCalendar(test)); + assert.throws( + TypeError, () => plainDate.until("2022-06-20", { largestUnit: "years" }), + `Expected error with ${description}` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js new file mode 100644 index 0000000000..65be788ce3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-mismatch.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown if calendars' id properties do not match +features: [Temporal] +---*/ + +const calendar1 = { + dateAdd() {}, + dateFromFields() {}, + dateUntil() {}, + day() {}, + dayOfWeek() {}, + dayOfYear() {}, + daysInMonth() {}, + daysInWeek() {}, + daysInYear() {}, + fields() {}, + id: "A", + inLeapYear() {}, + mergeFields() {}, + month() {}, + monthCode() {}, + monthDayFromFields() {}, + monthsInYear() {}, + weekOfYear() {}, + year() {}, + yearMonthFromFields() {}, + yearOfWeek() {}, +}; +const calendar2 = { + dateAdd() {}, + dateFromFields() {}, + dateUntil() {}, + day() {}, + dayOfWeek() {}, + dayOfYear() {}, + daysInMonth() {}, + daysInWeek() {}, + daysInYear() {}, + fields() {}, + id: "B", + inLeapYear() {}, + mergeFields() {}, + month() {}, + monthCode() {}, + monthDayFromFields() {}, + monthsInYear() {}, + weekOfYear() {}, + year() {}, + yearMonthFromFields() {}, + yearOfWeek() {}, +}; + +const plainDate1 = new Temporal.PlainDate(2000, 1, 1, calendar1); +const plainDate2 = new Temporal.PlainDate(2000, 1, 1, calendar2); +assert.throws(RangeError, () => plainDate1.until(plainDate2)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js new file mode 100644 index 0000000000..4f03a0b94d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaindate.prototype.until step 3: + 3. Set _other_ to ? ToTemporalDate(_other_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => { + const date = new Temporal.PlainDate(2000, 5, 2, temporalObject); + date.until({ year: 2005, month: 6, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/custom.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/custom.js new file mode 100644 index 0000000000..c2d9d2cb82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/custom.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Basic tests with custom calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const result = new Temporal.Duration(1, 3, 5, 7, 9); +const options = { largestUnit: "years" }; +let calls = 0; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateUntil(...args) { + ++calls; + assert.sameValue(args.length, 3, "Three arguments"); + assert.sameValue(args[0], plainDate, "First argument"); + assert.sameValue(args[1], other, "Second argument"); + assert.sameValue(args[2].largestUnit, "year", "Third argument: largestUnit"); + return result; + } +} +const calendar = new CustomCalendar(); +const plainDate = new Temporal.PlainDate(1976, 11, 18, calendar); +const other = new Temporal.PlainDate(2022, 6, 20, calendar); +TemporalHelpers.assertDuration(plainDate.until(other, options), + 1, 3, 5, 7, 0, 0, 0, 0, 0, 0, "result"); +assert.sameValue(calls, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js new file mode 100644 index 0000000000..72ff38ca21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-month.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should take length of month into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2019-02-01"); +const plainDate3 = Temporal.PlainDate.from("2019-03-01"); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 31, 0, 0, 0, 0, 0, 0, "January 2019"); +TemporalHelpers.assertDuration(plainDate2.until(plainDate3), 0, 0, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "February 2019"); + +const plainDate4 = Temporal.PlainDate.from("2020-02-01"); +const plainDate5 = Temporal.PlainDate.from("2020-03-01"); +TemporalHelpers.assertDuration(plainDate4.until(plainDate5), 0, 0, 0, /* days = */ 29, 0, 0, 0, 0, 0, 0, "February 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js new file mode 100644 index 0000000000..6ca8c59327 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/days-in-year.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should take length of year into account. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainDate1 = Temporal.PlainDate.from("2019-01-01"); +const plainDate2 = Temporal.PlainDate.from("2020-01-01"); +const plainDate3 = Temporal.PlainDate.from("2021-01-01"); +TemporalHelpers.assertDuration(plainDate1.until(plainDate2), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From January 2019"); +TemporalHelpers.assertDuration(plainDate2.until(plainDate3), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From January 2020"); + +const plainDate4 = Temporal.PlainDate.from("2019-06-01"); +const plainDate5 = Temporal.PlainDate.from("2020-06-01"); +const plainDate6 = Temporal.PlainDate.from("2021-06-01"); +TemporalHelpers.assertDuration(plainDate4.until(plainDate5), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "From June 2019"); +TemporalHelpers.assertDuration(plainDate5.until(plainDate6), 0, 0, 0, /* days = */ 365, 0, 0, 0, 0, 0, 0, "From June 2020"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..6bd0c01f29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaindate.prototype.until +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.until({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.until({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js new file mode 100644 index 0000000000..907df1f977 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Default value for largestUnit option is days +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb20.until(feb21), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no options"); +TemporalHelpers.assertDuration(feb20.until(feb21, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined options"); +TemporalHelpers.assertDuration(feb20.until(feb21, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "auto"); +TemporalHelpers.assertDuration(feb20.until(feb21, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js new file mode 100644 index 0000000000..a8f8812d9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with higher largestUnit than the default of 'days' +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const later = Temporal.PlainDate.from({ year: 2019, month: 7, day: 24 }); +const duration = date.until(later, { largestUnit: "years" }); +TemporalHelpers.assertDuration(duration, /* years = */ 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, "crossing epoch"); + +const feb20 = Temporal.PlainDate.from("2020-02-01"); +const feb21 = Temporal.PlainDate.from("2021-02-01"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, years"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, "start of February, weeks"); + +const lastFeb20 = Temporal.PlainDate.from("2020-02-29"); +const lastFeb21 = Temporal.PlainDate.from("2021-02-28"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, years"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, months"); +TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js new file mode 100644 index 0000000000..145b8d3024 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when largestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 0000000000..84769e1877 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 0000000000..91ba76b412 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const units = ["years", "months", "weeks", "days"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js new file mode 100644 index 0000000000..0b24449663 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default largestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js new file mode 100644 index 0000000000..42d56c641e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "year", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js new file mode 100644 index 0000000000..31c204731d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Temporal.PlainDate.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js new file mode 100644 index 0000000000..99b7ae2be1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Temporal.PlainDate.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainDate.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js new file mode 100644 index 0000000000..2d4a6df0d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + Temporal.PlainDate.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainDate.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainDate.prototype.until), false, + "isConstructor(Temporal.PlainDate.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-object.js new file mode 100644 index 0000000000..978d5189f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-object.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(2000, 5, 2); + +const result1 = instance.until(new Temporal.PlainDate(1976, 11, 18), {}); +TemporalHelpers.assertDuration( + result1, 0, 0, 0, -8566, 0, 0, 0, 0, 0, 0, + "options may be an empty plain object" +); + +const result2 = instance.until(new Temporal.PlainDate(1976, 11, 18), () => {}); +TemporalHelpers.assertDuration( + result2, 0, 0, 0, -8566, 0, 0, 0, 0, 0, 0, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js new file mode 100644 index 0000000000..dd67a3bd6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.PlainDate(1976, 11, 18), value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js new file mode 100644 index 0000000000..427670784a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js @@ -0,0 +1,214 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Properties on objects passed to until() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + // ToTemporalDate + "get other.calendar", + "has other.calendar.dateAdd", + "has other.calendar.dateFromFields", + "has other.calendar.dateUntil", + "has other.calendar.day", + "has other.calendar.dayOfWeek", + "has other.calendar.dayOfYear", + "has other.calendar.daysInMonth", + "has other.calendar.daysInWeek", + "has other.calendar.daysInYear", + "has other.calendar.fields", + "has other.calendar.id", + "has other.calendar.inLeapYear", + "has other.calendar.mergeFields", + "has other.calendar.month", + "has other.calendar.monthCode", + "has other.calendar.monthDayFromFields", + "has other.calendar.monthsInYear", + "has other.calendar.weekOfYear", + "has other.calendar.year", + "has other.calendar.yearMonthFromFields", + "has other.calendar.yearOfWeek", + "get other.calendar.dateFromFields", + "get other.calendar.fields", + "call other.calendar.fields", + "get other.day", + "get other.day.valueOf", + "call other.day.valueOf", + "get other.month", + "get other.month.valueOf", + "call other.month.valueOf", + "get other.monthCode", + "get other.monthCode.toString", + "call other.monthCode.toString", + "get other.year", + "get other.year.valueOf", + "call other.year.valueOf", + "call other.calendar.dateFromFields", + // CalendarEquals + "get this.calendar.id", + "get other.calendar.id", + // CopyDataProperties + "ownKeys options", + "getOwnPropertyDescriptor options.roundingIncrement", + "get options.roundingIncrement", + "getOwnPropertyDescriptor options.roundingMode", + "get options.roundingMode", + "getOwnPropertyDescriptor options.largestUnit", + "get options.largestUnit", + "getOwnPropertyDescriptor options.smallestUnit", + "get options.smallestUnit", + "getOwnPropertyDescriptor options.additional", + "get options.additional", + // GetDifferenceSettings + "get options.largestUnit.toString", + "call options.largestUnit.toString", + "get options.roundingIncrement.valueOf", + "call options.roundingIncrement.valueOf", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", +]; +const actual = []; + +const ownCalendar = TemporalHelpers.calendarObserver(actual, "this.calendar"); +const instance = new Temporal.PlainDate(2000, 5, 2, ownCalendar); + +const otherDatePropertyBag = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 6, + monthCode: "M06", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); + +function createOptionsObserver({ smallestUnit = "days", largestUnit = "auto", roundingMode = "halfExpand", roundingIncrement = 1 } = {}) { + return TemporalHelpers.propertyBagObserver(actual, { + // order is significant, due to iterating through properties in order to + // copy them to an internal null-prototype object: + roundingIncrement, + roundingMode, + largestUnit, + smallestUnit, + additional: "property", + }, "options"); +} + +// clear any observable things that happened while constructing the objects +actual.splice(0); + +// basic order of observable operations with calendar call, without rounding: +instance.until(otherDatePropertyBag, createOptionsObserver({ largestUnit: "years" })); +assert.compareArray(actual, expected.concat([ + // lookup + "get this.calendar.dateAdd", + "get this.calendar.dateUntil", + // CalendarDateUntil + "call this.calendar.dateUntil", +]), "order of operations"); +actual.splice(0); // clear + +// short-circuit for identical objects: + +const identicalPropertyBag = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); + +instance.since(identicalPropertyBag, createOptionsObserver()); +assert.compareArray(actual, expected, "order of operations with identical dates"); +actual.splice(0); // clear + +// code path through RoundDuration that rounds to the nearest year: +const expectedOpsForYearRounding = expected.concat([ + // lookup + "get this.calendar.dateAdd", + "get this.calendar.dateUntil", + // CalendarDateUntil + "call this.calendar.dateUntil", + // RoundDuration + "call this.calendar.dateAdd", // 12.d + "call this.calendar.dateAdd", // 12.f + "call this.calendar.dateUntil", // 12.n + "call this.calendar.dateAdd", // 12.x MoveRelativeDate + // (12.r not called because other units can't add up to >1 year at this point) + // BalanceDateDurationRelative + "call this.calendar.dateAdd", // 9.c + "call this.calendar.dateUntil" // 9.d +]); +instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); +actual.splice(0); // clear + +// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call: +const otherDatePropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), +}, "other"); +const expectedOpsForYearRoundingSameMonth = expected.concat([ + // lookup + "get this.calendar.dateAdd", + "get this.calendar.dateUntil", + // CalendarDateUntil + "call this.calendar.dateUntil", + // RoundDuration + "call this.calendar.dateAdd", // 12.d + "call this.calendar.dateAdd", // 12.f + "call this.calendar.dateAdd", // 12.x MoveRelativeDate + // (12.n not called because months and weeks == 0) + // BalanceDateDurationRelative + "call this.calendar.dateAdd", // 9.c + "call this.calendar.dateUntil" // 9.d +]); +instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); +assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); +actual.splice(0); // clear + +// code path through RoundDuration that rounds to the nearest month: +const expectedOpsForMonthRounding = expected.concat([ + // lookup + "get this.calendar.dateAdd", + "get this.calendar.dateUntil", + // CalendarDateUntil + "call this.calendar.dateUntil", + // RoundDuration + "call this.calendar.dateAdd", // 13.c + "call this.calendar.dateAdd", // 13.e + "call this.calendar.dateAdd", // 13.w MoveRelativeDate + // BalanceDateDurationRelative + "call this.calendar.dateAdd", // 10.d + "call this.calendar.dateUntil" // 10.e +]); +instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "months" })); +assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); +actual.splice(0); // clear + +// code path through RoundDuration that rounds to the nearest week: +const expectedOpsForWeekRounding = expected.concat([ + // lookup + "get this.calendar.dateAdd", + "get this.calendar.dateUntil", + // CalendarDateUntil + "call this.calendar.dateUntil", + // RoundDuration + "call this.calendar.dateUntil", // 14.f + "call this.calendar.dateAdd", // 14.p MoveRelativeDate + // BalanceDateDurationRelative + "call this.calendar.dateAdd", // 16 + "call this.calendar.dateUntil" // 17 +]); +instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); +assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js new file mode 100644 index 0000000000..0c230a999e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: The "until" property of Temporal.PlainDate.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainDate.prototype.until, + "function", + "`typeof PlainDate.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainDate.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/round-cross-unit-boundary.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/round-cross-unit-boundary.js new file mode 100644 index 0000000000..6b15e24902 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/round-cross-unit-boundary.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Rounding can cross unit boundaries up to largestUnit +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2022, 1, 1); +const later = new Temporal.PlainDate(2023, 12, 25); +const duration = earlier.until(later, { largestUnit: "years", smallestUnit: "months", roundingMode: "expand" }); +TemporalHelpers.assertDuration(duration, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "1 year 11 months balances to 2 years"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js new file mode 100644 index 0000000000..b7b28c9338 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-relative.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Should round relative to the receiver. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date1 = Temporal.PlainDate.from("2019-01-01"); +const date2 = Temporal.PlainDate.from("2019-02-15"); + +TemporalHelpers.assertDuration( + date1.until(date2, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 2, 0, 0, 0, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration( + date2.until(date1, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ -1, 0, 0, 0, 0, 0, 0, 0, 0); + +const cases = [ + ["2019-03-01", "2019-01-29", 1, 1], + ["2019-01-29", "2019-03-01", -1, -3], + ["2019-03-29", "2019-01-30", 1, 29], + ["2019-01-30", "2019-03-29", -1, -29], + ["2019-03-30", "2019-01-31", 1, 30], + ["2019-01-31", "2019-03-30", -1, -28], + ["2019-03-31", "2019-01-31", 2, 0], + ["2019-01-31", "2019-03-31", -2, 0] +]; +for (const [end, start, months, days] of cases) { + const result = Temporal.PlainDate.from(start).until(end, { largestUnit: "months" }); + TemporalHelpers.assertDuration(result, 0, months, 0, days, 0, 0, 0, 0, 0, 0, `${end} - ${start}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-zero-year-month-week-length.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-zero-year-month-week-length.js new file mode 100644 index 0000000000..1d56c472c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/rounding-zero-year-month-week-length.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + A malicious calendar resulting in a year, month, or week length of zero is + handled correctly +info: | + RoundDuration + 10.z. If _oneYearDays_ = 0, throw a *RangeError* exception. + ... + 11.z. If _oneMonthDays_ = 0, throw a *RangeError* exception. + ... + 12.s. If _oneWeekDays_ = 0, throw a *RangeError* exception. +features: [Temporal] +---*/ + +const cal = new class extends Temporal.Calendar { + dateAdd(date, duration, options) { + // Called several times, last call sets oneYear/Month/WeekDays to 0 + return new Temporal.PlainDate(1970, 1, 1); + } +}("iso8601"); + +const d1 = new Temporal.PlainDate(1970, 1, 1, cal); +const d2 = new Temporal.PlainDate(1971, 1, 1, cal); + +assert.throws(RangeError, () => d1.until(d2, { smallestUnit: "years" }), "zero year length handled correctly"); +assert.throws(RangeError, () => d1.until(d2, { smallestUnit: "months" }), "zero month length handled correctly"); +assert.throws(RangeError, () => d1.until(d2, { smallestUnit: "weeks" }), "zero week length handled correctly"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js new file mode 100644 index 0000000000..7e68bdd813 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 0000000000..349135ad08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Rounding for roundingIncrement option +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +const result = earlier.until(later, { roundingIncrement: 2.5, roundingMode: "trunc" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, "roundingIncrement 2.5 truncates to 2"); +const result2 = earlier.until(later, { smallestUnit: "days", roundingIncrement: 1e9 + 0.5, roundingMode: "expand" }); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 1e9, 0, 0, 0, 0, 0, 0, "roundingIncrement 1e9 + 0.5 truncates to 1e9"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 0000000000..26092686df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0.9 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 1e9 + 1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js new file mode 100644 index 0000000000..7670614029 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, "default roundingIncrement is 1"); + +// See options-undefined.js for {} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 0000000000..c2cc289fb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaindate.prototype.until step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2000, 5, 7); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js new file mode 100644 index 0000000000..5a86e247c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingincrement.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingIncrement: 4, roundingMode: "halfExpand" }), + /* years = */ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingIncrement: 10, roundingMode: "halfExpand" }), + 0, /* months = */ 30, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingIncrement: 12, roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 144, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "days", roundingIncrement: 100, roundingMode: "halfExpand" }), + 0, 0, 0, /* days = */ 1000, 0, 0, 0, 0, 0, 0, "days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js new file mode 100644 index 0000000000..fe40fdd5f1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-ceil.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-2]], + ["months", [0, 32], [0, -31]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "ceil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-expand.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-expand.js new file mode 100644 index 0000000000..d3b3271b50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-expand.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "expand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "expand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js new file mode 100644 index 0000000000..37c8a1c1a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-floor.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [2], [-3]], + ["months", [0, 31], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "floor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfCeil.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfCeil.js new file mode 100644 index 0000000000..55118dd705 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfCeil.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfCeil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "halfCeil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfEven.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfEven.js new file mode 100644 index 0000000000..3b42461cdb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfEven.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfEven". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "halfEven"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js new file mode 100644 index 0000000000..c5fc068b82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfExpand.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "halfExpand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfFloor.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfFloor.js new file mode 100644 index 0000000000..b4f0c8f767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfFloor.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfFloor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "halfFloor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfTrunc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfTrunc.js new file mode 100644 index 0000000000..abd790fe34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-halfTrunc.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "halfTrunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [3], [-3]], + ["months", [0, 32], [0, -32]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "halfTrunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 0000000000..7cc40d387e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js new file mode 100644 index 0000000000..43cbe4a1f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-trunc.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2019, 1, 8); +const later = new Temporal.PlainDate(2021, 9, 7); + +const expected = [ + ["years", [2], [-2]], + ["months", [0, 31], [0, -31]], + ["weeks", [0, 0, 139], [0, 0, -139]], + ["days", [0, 0, 0, 973], [0, 0, 0, -973]], +]; + +const roundingMode = "trunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js new file mode 100644 index 0000000000..0370a2e95a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-undefined.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 1, 1); + +const later1 = new Temporal.PlainDate(2005, 2, 20); +const explicit1 = earlier.until(later1, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit1 = earlier.until(later1, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +const later2 = new Temporal.PlainDate(2005, 12, 15); +const explicit2 = earlier.until(later2, { smallestUnit: "year", roundingMode: undefined }); +TemporalHelpers.assertDuration(explicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); +const implicit2 = earlier.until(later2, { smallestUnit: "year" }); +TemporalHelpers.assertDuration(implicit2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 0000000000..0c95403f84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "year", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js new file mode 100644 index 0000000000..e6cd7b717a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-higher-units.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Tests calculations with higher smallestUnit than the default of "days" +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainDate.from("2019-01-08"); +const later = Temporal.PlainDate.from("2021-09-07"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "years", roundingMode: "halfExpand" }), + /* years = */ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, "years"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "months", roundingMode: "halfExpand" }), + 0, /* months = */ 32, 0, 0, 0, 0, 0, 0, 0, 0, "months"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "weeks", roundingMode: "halfExpand" }), + 0, 0, /* weeks = */ 139, 0, 0, 0, 0, 0, 0, 0, "weeks"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 0000000000..6979d8f13c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 0000000000..75f6d73609 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 12); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js new file mode 100644 index 0000000000..359541c4f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); + +const explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, "default smallestUnit is day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 0000000000..f257997db1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainDate(2000, 5, 2); +const later = new Temporal.PlainDate(2001, 6, 3); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "year", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js new file mode 100644 index 0000000000..54dbd17bc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/weeks-months.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: until() should not return weeks and months together. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const date = new Temporal.PlainDate(1969, 7, 24); +const laterDate = new Temporal.PlainDate(1969, 9, 4); +TemporalHelpers.assertDuration(date.until(laterDate, { largestUnit: "weeks" }), + 0, 0, /* weeks = */ 6, 0, 0, 0, 0, 0, 0, 0, "weeks"); +TemporalHelpers.assertDuration(date.until(laterDate, { largestUnit: "months" }), + 0, /* months = */ 1, 0, 11, 0, 0, 0, 0, 0, 0, "months"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js new file mode 100644 index 0000000000..f92ca0a5e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainDate/prototype/until/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T00:45", + "-000000-10-31T00:45+01:00", + "-000000-10-31T00:45+00:00[UTC]", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); |