diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/src/tests/test262/built-ins/Temporal/Calendar | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/test262/built-ins/Temporal/Calendar')
904 files changed, 26468 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/argument-wrong-type.js new file mode 100644 index 0000000000..c78fd3f8cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/argument-wrong-type.js @@ -0,0 +1,33 @@ +// |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.calendar +description: RangeError thrown when constructor invoked with the wrong type +features: [Temporal] +---*/ + +const tests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [19761118, "number that would convert to a valid ISO string in other contexts"], + [1n, "bigint"], + [Symbol(), "symbol"], + [{}, "object not implementing any protocol"], + [new Temporal.Calendar("iso8601"), "calendar instance"], + [new Temporal.TimeZone("UTC"), "time zone instance"], + [Temporal.ZonedDateTime.from("2020-01-01T00:00Z[UTC]"), "ZonedDateTime instance"], +]; + +for (const [arg, description] of tests) { + assert.throws( + typeof (arg) === "string" ? RangeError : TypeError, + () => new Temporal.Calendar(arg), + `${description} is not accepted by this constructor` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js new file mode 100644 index 0000000000..1862b77310 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Tests that Temporal.Calendar meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.Calendar.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js new file mode 100644 index 0000000000..9061f4adce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Temporal.Calendar constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.Calendar("iso8601")); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js new file mode 100644 index 0000000000..7eef95f8f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Tests that Temporal.Calendar.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-case-insensitive.js new file mode 100644 index 0000000000..a99f743a01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-case-insensitive.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Calendar names are case-insensitive +features: [Temporal] +---*/ + +const arg = "iSo8601"; + +const result = Temporal.Calendar.from(arg); +assert.sameValue(result.id, "iso8601", "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-number.js new file mode 100644 index 0000000000..4ae7fa5dc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-number.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: A number is not allowed to be a calendar +features: [Temporal] +---*/ + +const numbers = [ + 1, + -19761118, + 19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => Temporal.Calendar.from(arg), + "A number is not a valid ISO string for Calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js new file mode 100644 index 0000000000..fdbe8b5a47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-object.js @@ -0,0 +1,38 @@ +// |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.calendar.from +description: > + Converting an object implementing the Calendar protocol to Temporal.Calendar + gives the same object +features: [Temporal] +---*/ + +const custom = { + dateAdd() {}, + dateFromFields() {}, + dateUntil() {}, + day() {}, + dayOfWeek() {}, + dayOfYear() {}, + daysInMonth() {}, + daysInWeek() {}, + daysInYear() {}, + fields() {}, + id: "custom-calendar", + inLeapYear() {}, + mergeFields() {}, + month() {}, + monthCode() {}, + monthDayFromFields() {}, + monthsInYear() {}, + weekOfYear() {}, + year() {}, + yearMonthFromFields() {}, + yearOfWeek() {}, +}; +assert.sameValue(Temporal.Calendar.from(custom), custom); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.js new file mode 100644 index 0000000000..5fca567d39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-builtin.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.calendar.from +description: Calendar.from should support iso8601. +features: [Temporal] +---*/ + +const tests = [ + "iso8601", + "1994-11-05T08:15:30-05:00", +]; + +for (const item of tests) { + const calendar = Temporal.Calendar.from(item); + assert(calendar instanceof Temporal.Calendar); + assert.sameValue(calendar.id, "iso8601"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-leap-second.js new file mode 100644 index 0000000000..f6d01b0160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-leap-second.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.calendar.from +description: Leap second is a valid ISO string for Calendar +features: [Temporal] +---*/ + +const arg = "2016-12-31T23:59:60"; +const result = Temporal.Calendar.from(arg); +assert.sameValue( + result.id, + "iso8601", + "leap second is a valid ISO string for Calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.js new file mode 100644 index 0000000000..bb4a361de3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string-not-builtin.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.calendar.from +description: from() throws if the argument is not a built-in calendar name. +features: [Temporal] +---*/ + +const tests = [ + "local", + "iso-8601", + "[u-ca=iso8601]", + "invalid-calendar", +]; + +for (const item of tests) { + assert.throws(RangeError, () => Temporal.Calendar.from(item)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string.js new file mode 100644 index 0000000000..b51ea04a48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const arg = "iso8601"; + +const result = Temporal.Calendar.from(arg); +assert.sameValue(result.id, "iso8601", `Calendar created from string "${arg}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js new file mode 100644 index 0000000000..f1b5cfde92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-temporal-object.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal-totemporalcalendar step 1.b: + b. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js] +features: [Temporal] +---*/ + +const plainDate = new Temporal.PlainDate(2000, 5, 2); +const plainDateTime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const plainMonthDay = new Temporal.PlainMonthDay(5, 2); +const plainYearMonth = new Temporal.PlainYearMonth(2000, 5); +const zonedDateTime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + +[plainDate, plainDateTime, plainMonthDay, plainYearMonth, zonedDateTime].forEach((arg) => { + const actual = []; + const expected = []; + + const calendar = arg.getISOFields().calendar; + + Object.defineProperty(arg, "calendar", { + get() { + actual.push("get calendar"); + return calendar; + }, + }); + + const result = Temporal.Calendar.from(arg); + assert.sameValue(result.id, calendar, "Temporal object coerced to calendar"); + + assert.compareArray(actual, expected, "calendar getter not called"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-wrong-type.js new file mode 100644 index 0000000000..f28985ddb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/calendar-wrong-type.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or object for Calendar +features: [BigInt, Symbol, Temporal] +---*/ + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => Temporal.Calendar.from(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object that doesn't implement the protocol"], + [new Temporal.TimeZone("UTC"), "time zone instance"], + [Temporal.Calendar, "Temporal.Calendar, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => Temporal.Calendar.from(arg), `${description} is not a valid object and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js new file mode 100644 index 0000000000..21dd13cb33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Temporal.Calendar.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/name.js new file mode 100644 index 0000000000..4fb450918a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/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.calendar.from +description: Temporal.Calendar.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js new file mode 100644 index 0000000000..6aa43c2f7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: Temporal.Calendar.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.from), false, + "isConstructor(Temporal.Calendar.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js new file mode 100644 index 0000000000..2c46579d05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.from +description: The "from" property of Temporal.Calendar +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.from, + "function", + "`typeof Calendar.from` is `function`" +); + +verifyProperty(Temporal.Calendar, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.js new file mode 100644 index 0000000000..a585c93929 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/from/subclassing-ignored.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.calendar.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.Calendar, + "from", + ["iso8601"], + (result) => { + assert.sameValue(result.id, "iso8601", "id property of result"); + assert.sameValue(result.toString(), "iso8601", "toString() of result"); + }, +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/length.js new file mode 100644 index 0000000000..d4e68a9ec7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: Temporal.Calendar.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.Calendar, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js b/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js new file mode 100644 index 0000000000..8d445ea24f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/missing-arguments.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar +description: RangeError thrown when constructor invoked with no argument +features: [Temporal] +---*/ + +assert.throws(TypeError, () => new Temporal.Calendar()); +assert.throws(TypeError, () => new Temporal.Calendar(undefined)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/name.js new file mode 100644 index 0000000000..0c7faefa8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/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.calendar +description: Temporal.Calendar.name is "Calendar" +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.Calendar, "name", { + value: "Calendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prop-desc.js new file mode 100644 index 0000000000..20748688e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/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.calendar +description: The "Calendar" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar, + "function", + "`typeof Calendar` is `function`" +); + +verifyProperty(Temporal, "Calendar", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/constructor.js new file mode 100644 index 0000000000..9b0bc3dc60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/constructor.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.constructor +description: Test for Temporal.Calendar.prototype.constructor. +info: The initial value of Temporal.Calendar.prototype.constructor is %Temporal.Calendar%. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype, "constructor", { + value: Temporal.Calendar, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-days.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-days.js new file mode 100644 index 0000000000..edf4f9b2f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-days.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with days and calculate correctly.. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p10d = new Temporal.Duration(0,0,0,10); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-16", p10d), 2021, 7, "M07", 26, + "add 10 days and result into the same month"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-26", p10d), 2021, 8, "M08", 5, + "add 10 days and result into next month"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-26", p10d), 2022, 1, "M01", 5, + "add 10 days and result into next year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-26", p10d), 2020, 3, "M03", 7, + "add 10 days from a leap year in Feb and result into March"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-26", p10d), 2021, 3, "M03", 8, + "add 10 days from a non leap year in Feb and result into March"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-19", p10d), 2020, 2, "M02", 29, + "add 10 days from a leap year in Feb 19 and result into Feb 29"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-19", p10d), 2021, 3, "M03", 1, + "add 10 days from a non leap year in Feb 19 and result into March 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months-weeks.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months-weeks.js new file mode 100644 index 0000000000..7f3ac6e052 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months-weeks.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with months and weeks and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p2m3w = new Temporal.Duration(0,2,3); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-29", p2m3w), 2020, 5, "M05", 20, + "add two months 3 weeks from Feb 29 of a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-28", p2m3w), 2020, 5, "M05", 19, + "add two months 3 weeks from Feb 28 of a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-28", p2m3w), 2021, 5, "M05", 19, + "add two months 3 weeks from Feb 28 of a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-12-28", p2m3w), 2021, 3, "M03", 21, + "add two months 3 weeks from end of year to non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-12-28", p2m3w), 2020, 3, "M03", 20, + "add two months 3 weeks from end of year to leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-10-28", p2m3w), 2020, 1, "M01", 18, + "add two months 3 weeks and cause roll into a new year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-10-31", p2m3w), 2020, 1, "M01", 21, + "add two months 3 weeks and cause roll into a new year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months.js new file mode 100644 index 0000000000..592b16f2fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-months.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with months and calculate correctly +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p5m = new Temporal.Duration(0, 5); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-16", p5m), 2021, 12, "M12", 16, + "add five months and result in the same year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-08-16", p5m), 2022, 1, "M01", 16, + "add five months and result in the next year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-10-31", p5m), 2022, 3, "M03", 31, + "add five months and result in the next year in end of month"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-10-01", p5m), 2020, 3, "M03", 1, + "add five months and result in the next year in end of month on leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-09-30", p5m), 2022, 2, "M02", 28, + "add five months and result in the nexdt year and constrain to Feb 28"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-09-30", p5m), 2020, 2, "M02", 29, + "add five months and result in the nexdt year and constrain to Feb 29 on leap year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks-days.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks-days.js new file mode 100644 index 0000000000..9489dd63ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks-days.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with weeks and days and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p2w3d = new Temporal.Duration(0,0,2,3); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-29", p2w3d), 2020, 3, "M03", 17, + "add 2 weeks and 3 days (17 days) from Feb 29 in a leap year and cause rolling into March"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-28", p2w3d), 2021, 3, "M03", 17, + "add 2 weeks and 3 days (17 days) from Feb and cause rolling into March in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-28", p2w3d), 2020, 3, "M03", 16, + "add 2 weeks and 3 days (17 days) from Feb and cause rolling into March in a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-12-28", p2w3d), 2021, 1, "M01", 14, + "add 2 weeks and 3 days (17 days) and cause rolling into a new year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks.js new file mode 100644 index 0000000000..671bd83bfe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-weeks.js @@ -0,0 +1,66 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with weeks and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p1w = new Temporal.Duration(0,0,1); +let p6w = new Temporal.Duration(0,0,6); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-19", p1w), 2021, 2, "M02", 26, + "add one week in Feb"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-27", p1w), 2021, 3, "M03", 6, + "add one week in Feb and result in March"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-27", p1w), 2020, 3, "M03", 5, + "add one week in Feb and result in March in a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-24", p1w), 2021, 12, "M12", 31, + "add one week and result in the last day of a year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-25", p1w), 2022, 1, "M01", 1, + "add one week and result in the first day of next year"); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-01-27", p1w), 2021, 2, "M02", 3, + "add one week and result in next month from a month with 31 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-06-27", p1w), 2021, 7, "M07", 4, + "add one week and result in next month from a month with 30 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-27", p1w), 2021, 8, "M08", 3, + "add one week and result in next month from a month with 31 days"); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-19", p6w), 2021, 4, "M04", 2, + "add six weeks and result in next month from Feb in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-19", p6w), 2020, 4, "M04", 1, + "add six weeks and result in next month from Feb in a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-24", p6w), 2022, 2, "M02", 4, + "add six weeks and result in the next year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-01-27", p6w), 2021, 3, "M03", 10, + "add six weeks and result in the same year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-01-27", p6w), 2020, 3, "M03", 9, + "add six weeks and result in the same year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-06-27", p6w), 2021, 8, "M08", 8, + "add six weeks and result in the same year crossing month of 30 and 31 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-27", p6w), 2021, 9, "M09", 7, + "add six weeks and result in the same year crossing month of 31 and 31 days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months-days.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months-days.js new file mode 100644 index 0000000000..1a7c932a3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months-days.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with years, months and days and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p1y2m4d = new Temporal.Duration(1,2,0,4); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-16", p1y2m4d), 2022, 9, "M09", 20, + "add one year two months and 4 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-27", p1y2m4d), 2022, 5, "M05", 1, + "add one year two months and 4 days and roll into new month from a month of 30 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-01-28", p1y2m4d), 2022, 4, "M04", 1, + "add one year two months and 4 days and roll into new month from a month of 31 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-26", p1y2m4d), 2022, 4, "M04", 30, + "add one year two months and 4 days which roll from March to April in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2023-02-26", p1y2m4d), 2024, 4, "M04", 30, + "add one year two months and 4 days which roll from March to April in a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-30", p1y2m4d), 2023, 3, "M03", 4, + "add one year two months and 4 days which roll month into new year and roll day into March in non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2022-12-30", p1y2m4d), 2024, 3, "M03", 4, + "add one year two months and 4 days which roll month into new year and roll day into March in leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2022-12-29", p1y2m4d), 2024, 3, "M03", 4, + "add one year two months and 4 days which roll month into new year and roll day into March in leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-30", p1y2m4d), 2022, 10, "M10", 4, + "add one year two months and 4 days which roll into a new month from a month with 30 days"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-06-30", p1y2m4d), 2022, 9, "M09", 3, + "add one year two months and 4 days which roll into a new month from a month with 31 days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months.js new file mode 100644 index 0000000000..4a3d984335 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-months.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with years and months and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p1y2m = new Temporal.Duration(1,2); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-16", p1y2m), 2022, 9, "M09", 16, + "add one year and 2 months"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-11-30", p1y2m), 2023, 1, "M01", 30, + "add one year and 2 months roll into a new year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-12-31", p1y2m), 2023, 2, "M02", 28, + "add one year and 2 months roll into a new year and constrain in Feb 28 of a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2022-12-31", p1y2m), 2024, 2, "M02", 29, + "add one year and 2 months roll into a new year and constrain in Feb 29 of a leap year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-weeks.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-weeks.js new file mode 100644 index 0000000000..06bae12e5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years-weeks.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with years and weeks and calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p1y2w = new Temporal.Duration(1,0,2); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-28", p1y2w), 2021, 3, "M03", 14, + "add 1 year and 2 weeks to Feb 28 and cause roll into March in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-29", p1y2w), 2021, 3, "M03", 14, + "add 1 year and 2 weeks to Feb 29 and cause roll into March in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2019-02-28", p1y2w), 2020, 3, "M03", 13, + "add 1 year and 2 weeks to Feb 28 and cause roll into March in a leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-02-28", p1y2w), 2022, 3, "M03", 14, + "add 1 year and 2 weeks to Feb 28 and cause roll into March in a non leap year"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-12-28", p1y2w), 2022, 1, "M01", 11, + "add 1 year and 2 weeks and cause roll into a new year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years.js new file mode 100644 index 0000000000..c2e2eda6c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/add-years.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd add duration with years only calculate correctly. +info: | + 8. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], overflow). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let p1y = new Temporal.Duration(1); +let p4y = new Temporal.Duration(4); + +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-29", p1y), 2021, 2, "M02", 28, + "add one year on Feb 29"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2020-02-29", p4y), 2024, 2, "M02", 29, + "add four years on Feb 29"); +TemporalHelpers.assertPlainDate( + cal.dateAdd("2021-07-16", p1y), 2022, 7, "M07", 16, + "add one year on other date"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..2d9cb13d16 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.dateAdd(arg, new Temporal.Duration()); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..6a0f1f43b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.dateAdd(arg, new Temporal.Duration()); +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/Calendar/prototype/dateAdd/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..897312501c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dateAdd(arg, new Temporal.Duration())); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..1ad3bc8141 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.dateAdd(arg, new Temporal.Duration())); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-max.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-max.js new file mode 100644 index 0000000000..b6cc1edb0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-max.js @@ -0,0 +1,58 @@ +// |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.calendar.prototype.dateadd +description: Maximum allowed duration +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const maxCases = [ + ["P273790Y8M12DT23H59M59.999999999S", "string with max years"], + [{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"], + ["P3285488M12DT23H59M59.999999999S", "string with max months"], + [{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"], + ["P14285714W2DT23H59M59.999999999S", "string with max weeks"], + [{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"], + ["P100000000DT23H59M59.999999999S", "string with max days"], + [{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"], + ["PT2400000023H59M59.999999999S", "string with max hours"], + [{ hours: 2400000023, nanoseconds: 3599999999999 }, "property bag with max hours"], + ["PT144000001439M59.999999999S", "string with max minutes"], + [{ minutes: 144000001439, nanoseconds: 59999999999 }, "property bag with max minutes"], + ["PT8640000086399.999999999S", "string with max seconds"], + [{ seconds: 8640000086399, nanoseconds: 999999999 }, "property bag with max seconds"], +]; + +for (const [arg, descr] of maxCases) { + const result = instance.dateAdd(new Temporal.PlainDate(1970, 1, 1), arg); + TemporalHelpers.assertPlainDate(result, 275760, 9, "M09", 13, `operation succeeds with ${descr}`); +} + +const minCases = [ + ["-P273790Y8M12DT23H59M59.999999999S", "string with min years"], + [{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"], + ["-P3285488M12DT23H59M59.999999999S", "string with min months"], + [{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"], + ["-P14285714W3DT23H59M59.999999999S", "string with min weeks"], + [{ weeks: -14285714, days: -3, nanoseconds: -86399999999999 }, "property bag with min weeks"], + ["-P100000001DT23H59M59.999999999S", "string with min days"], + [{ days: -100000001, nanoseconds: -86399999999999 }, "property bag with min days"], + ["-PT2400000047H59M59.999999999S", "string with min hours"], + [{ hours: -2400000047, nanoseconds: -3599999999999 }, "property bag with min hours"], + ["-PT144000002879M59.999999999S", "string with min minutes"], + [{ minutes: -144000002879, nanoseconds: -59999999999 }, "property bag with min minutes"], + ["-PT8640000172799.999999999S", "string with min seconds"], + [{ seconds: -8640000172799, nanoseconds: -999999999 }, "property bag with min seconds"], +]; + +for (const [arg, descr] of minCases) { + const result = instance.dateAdd(new Temporal.PlainDate(1970, 1, 1), arg); + TemporalHelpers.assertPlainDate(result, -271821, 4, "M04", 19, `operation succeeds with ${descr}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-out-of-range.js new file mode 100644 index 0000000000..4368522992 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-out-of-range.js @@ -0,0 +1,75 @@ +// |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.calendar.prototype.dateadd +description: Duration-like argument that is out of range +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const cases = [ + // 2^32 = 4294967296 + ["P4294967296Y", "string with years > max"], + [{ years: 4294967296 }, "property bag with years > max"], + ["-P4294967296Y", "string with years < min"], + [{ years: -4294967296 }, "property bag with years < min"], + ["P4294967296M", "string with months > max"], + [{ months: 4294967296 }, "property bag with months > max"], + ["-P4294967296M", "string with months < min"], + [{ months: -4294967296 }, "property bag with months < min"], + ["P4294967296W", "string with weeks > max"], + [{ weeks: 4294967296 }, "property bag with weeks > max"], + ["-P4294967296W", "string with weeks < min"], + [{ weeks: -4294967296 }, "property bag with weeks < min"], + + // ceil(max safe integer / 86400) = 104249991375 + ["P104249991375D", "string with days > max"], + [{ days: 104249991375 }, "property bag with days > max"], + ["P104249991374DT24H", "string where hours balance into days > max"], + [{ days: 104249991374, hours: 24 }, "property bag where hours balance into days > max"], + ["-P104249991375D", "string with days < min"], + [{ days: -104249991375 }, "property bag with days < min"], + ["-P104249991374DT24H", "string where hours balance into days < min"], + [{ days: -104249991374, hours: -24 }, "property bag where hours balance into days < min"], + + // ceil(max safe integer / 3600) = 2501999792984 + ["PT2501999792984H", "string with hours > max"], + [{ hours: 2501999792984 }, "property bag with hours > max"], + ["PT2501999792983H60M", "string where minutes balance into hours > max"], + [{ hours: 2501999792983, minutes: 60 }, "property bag where minutes balance into hours > max"], + ["-PT2501999792984H", "string with hours < min"], + [{ hours: -2501999792984 }, "property bag with hours < min"], + ["-PT2501999792983H60M", "string where minutes balance into hours < min"], + [{ hours: -2501999792983, minutes: -60 }, "property bag where minutes balance into hours < min"], + + // ceil(max safe integer / 60) = 150119987579017 + ["PT150119987579017M", "string with minutes > max"], + [{ minutes: 150119987579017 }, "property bag with minutes > max"], + ["PT150119987579016M60S", "string where seconds balance into minutes > max"], + [{ minutes: 150119987579016, seconds: 60 }, "property bag where seconds balance into minutes > max"], + ["-PT150119987579017M", "string with minutes < min"], + [{ minutes: -150119987579017 }, "property bag with minutes < min"], + ["-PT150119987579016M60S", "string where seconds balance into minutes < min"], + [{ minutes: -150119987579016, seconds: -60 }, "property bag where seconds balance into minutes < min"], + + // 2^53 = 9007199254740992 + ["PT9007199254740992S", "string with seconds > max"], + [{ seconds: 9007199254740992 }, "property bag with seconds > max"], + [{ seconds: 9007199254740991, milliseconds: 1000 }, "property bag where milliseconds balance into seconds > max"], + [{ seconds: 9007199254740991, microseconds: 1000000 }, "property bag where microseconds balance into seconds > max"], + [{ seconds: 9007199254740991, nanoseconds: 1000000000 }, "property bag where nanoseconds balance into seconds > max"], + ["-PT9007199254740992S", "string with seconds < min"], + [{ seconds: -9007199254740992 }, "property bag with seconds < min"], + [{ seconds: -9007199254740991, milliseconds: -1000 }, "property bag where milliseconds balance into seconds < min"], + [{ seconds: -9007199254740991, microseconds: -1000000 }, "property bag where microseconds balance into seconds < min"], + [{ seconds: -9007199254740991, nanoseconds: -1000000000 }, "property bag where nanoseconds balance into seconds < min"], +]; + +for (const [arg, descr] of cases) { + assert.throws(RangeError, () => instance.dateAdd(new Temporal.PlainDate(1970, 1, 1), arg), `${descr} is out of range`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-years-and-months-number-max-value.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-years-and-months-number-max-value.js new file mode 100644 index 0000000000..dcbfed8b43 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-duration-years-and-months-number-max-value.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + Call BalanceISOYearMonth with 2³² - 1 and -(2³² - 1) for years/months. +info: | + Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] ) + + ... + 9. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], + duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], + overflow). + 10. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). + + AddISODate ( year, month, day, years, months, weeks, days, overflow ) + + ... + 3. Let intermediate be ! BalanceISOYearMonth(year + years, month + months). + ... + +features: [Temporal] +---*/ + +var cal = new Temporal.Calendar("iso8601"); +var date = new Temporal.PlainDate(1970, 1, 1); + +const max = 4294967295; // 2³² - 1 + +var maxValue = new Temporal.Duration(max, max); +var minValue = new Temporal.Duration(-max, -max); + +assert.throws(RangeError, () => cal.dateAdd(date, maxValue), "years/months is +Number.MAX_VALUE"); +assert.throws(RangeError, () => cal.dateAdd(date, minValue), "years/months is -Number.MAX_VALUE"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-leap-second.js new file mode 100644 index 0000000000..edca559552 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Leap second is a valid ISO string for PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.dateAdd(arg, new Temporal.Duration()); +TemporalHelpers.assertPlainDate( + result1, + 2016, 12, "M12", 31, + "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.dateAdd(arg, new Temporal.Duration()); +TemporalHelpers.assertPlainDate( + result2, + 2016, 12, "M12", 31, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-number.js new file mode 100644 index 0000000000..940952dd15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + '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/Calendar/prototype/dateAdd/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.js new file mode 100644 index 0000000000..a613cfe71e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-plaindatetime.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.calendar.prototype.dateadd +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + 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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(0, 1); + const result = calendar.dateAdd(datetime, duration); + TemporalHelpers.assertPlainDate(result, 2000, 6, "M06", 2); + assert.sameValue(result.hour, undefined, "instance of PlainDate returned, not PlainDateTime"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..b09b2939c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: The calendar name is case-insensitive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dateAdd(arg, new Temporal.Duration()); +TemporalHelpers.assertPlainDate(result, 1976, 11, "M11", 18, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..7517d61c18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Leap second is a valid ISO string for a calendar in a property bag +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dateAdd(arg, new Temporal.Duration()); +TemporalHelpers.assertPlainDate( + result, + 1976, 11, "M11", 18, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..80b3fcd76f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.dateAdd(arg, new Temporal.Duration()), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..cb12bd134f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: A calendar ID is valid input for Calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dateAdd(arg, new Temporal.Duration()); +TemporalHelpers.assertPlainDate(result, 1976, 11, "M11", 18, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..72fbbce9da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +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.dateAdd(arg, new Temporal.Duration()), + `${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.dateAdd(arg, new Temporal.Duration()), `${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/Calendar/prototype/dateAdd/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..2a93ec4ea9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..4e49748823 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dateAdd(arg, new Temporal.Duration())); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..c14ecfd721 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateAdd(arg, new Temporal.Duration()); + + TemporalHelpers.assertPlainDate( + result, + 2000, 5, "M05", 2, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..46728937ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..3d3cde244a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.dateAdd(arg, new Temporal.Duration()); + + TemporalHelpers.assertPlainDate( + result, + 2000, 5, "M05", 2, + `"${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.dateAdd(arg, new Temporal.Duration()), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js new file mode 100644 index 0000000000..94cd428d07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..edbc719aaf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..dfd6888026 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-time-separators.js new file mode 100644 index 0000000000..7480f0af4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateAdd(arg, new Temporal.Duration()); + + TemporalHelpers.assertPlainDate( + result, + 2000, 5, "M05", 2, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..e436365b1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateAdd(arg, new Temporal.Duration()); + + TemporalHelpers.assertPlainDate( + result, + 2000, 5, "M05", 2, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..f217d7e8b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateAdd(arg, new Temporal.Duration()); + + TemporalHelpers.assertPlainDate( + result, + 2000, 5, "M05", 2, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..0bf4e2177a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-wrong-type.js new file mode 100644 index 0000000000..0578415add --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +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.dateAdd(arg, new Temporal.Duration()), + `${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.dateAdd(arg, new Temporal.Duration()), `${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/Calendar/prototype/dateAdd/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..3908fb2f29 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.dateAdd(arg, new Temporal.Duration())); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..ef5dea755a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +instance.dateAdd(arg, new Temporal.Duration()); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..9155340af0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.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.calendar.prototype.dateadd +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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..5356882df5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.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.calendar.prototype.dateadd +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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dateAdd(datetime, duration), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..441f379188 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.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.calendar.prototype.dateadd +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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..4f7e73bdf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.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.calendar.prototype.dateadd +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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(1); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dateAdd(datetime, duration)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js new file mode 100644 index 0000000000..398ca6999f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/balance-smaller-units.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Durations with units smaller than days are balanced before adding +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(0, 0, 0, 1, 24, 1440, 86400, 86400_000, 86400_000_000, 86400_000_000_000); + +const result = calendar.dateAdd(date, duration); +TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +const resultString = calendar.dateAdd(date, "P1DT24H1440M86400S"); +TemporalHelpers.assertPlainDate(resultString, 2000, 5, "M05", 6, "units smaller than days are balanced"); + +const resultPropBag = calendar.dateAdd(date, { days: 1, hours: 24, minutes: 1440, seconds: 86400, milliseconds: 86400_000, microseconds: 86400_000_000, nanoseconds: 86400_000_000_000 }); +TemporalHelpers.assertPlainDate(resultPropBag, 2000, 5, "M05", 9, "units smaller than days are balanced"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js new file mode 100644 index 0000000000..2424570c74 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/basic.js @@ -0,0 +1,53 @@ +// |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.calendar.prototype.dateadd +description: Basic tests for dateAdd(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const date = Temporal.PlainDate.from("1994-11-06"); +const positiveDuration = Temporal.Duration.from({ months: 1, weeks: 1 }); +const negativeDuration = Temporal.Duration.from({ months: -1, weeks: -1 }); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(Temporal.PlainDateTime.from("1994-11-06T08:15:30"), positiveDuration, {}), + 1994, 12, "M12", 13, "date: PlainDateTime"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd({ year: 1994, month: 11, day: 6 }, positiveDuration, {}), + 1994, 12, "M12", 13, "date: property bag"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd("1994-11-06", positiveDuration, {}), + 1994, 12, "M12", 13, "date: string"); + +assert.throws(TypeError, () => iso.dateAdd({ month: 11 }, positiveDuration, {}), "date: missing property"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(date, { months: 1, weeks: 1 }, {}), + 1994, 12, "M12", 13, "duration: property bag"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(date, "P1M1W", {}), + 1994, 12, "M12", 13, "duration: string"); + +assert.throws(TypeError, () => iso.dateAdd(date, { month: 1 }, {}), "duration: missing property"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd(Temporal.PlainDateTime.from("1994-11-06T08:15:30"), negativeDuration, {}), + 1994, 9, "M09", 29, "date: PlainDateTime, negative duration"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd({ year: 1994, month: 11, day: 6 }, negativeDuration, {}), + 1994, 9, "M09", 29, "date: property bag, negative duration"); + +TemporalHelpers.assertPlainDate( + iso.dateAdd("1994-11-06", negativeDuration, {}), + 1994, 9, "M09", 29, "date: string, negative duration"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/branding.js new file mode 100644 index 0000000000..c1db178920 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const dateAdd = Temporal.Calendar.prototype.dateAdd; + +assert.sameValue(typeof dateAdd, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1), new Temporal.Duration(1)]; + +assert.throws(TypeError, () => dateAdd.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateAdd.apply(null, args), "null"); +assert.throws(TypeError, () => dateAdd.apply(true, args), "true"); +assert.throws(TypeError, () => dateAdd.apply("", args), "empty string"); +assert.throws(TypeError, () => dateAdd.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateAdd.apply(1, args), "1"); +assert.throws(TypeError, () => dateAdd.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateAdd.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateAdd.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/builtin.js new file mode 100644 index 0000000000..37351aff5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: > + Tests that Temporal.Calendar.prototype.dateAdd + 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.Calendar.prototype.dateAdd), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateAdd), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateAdd), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateAdd.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..bfad861fe3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +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(); +calendar.dateAdd({ year: 2000, month: 5, day: 2, calendar }, new Temporal.Duration(1)); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-fields-iterable.js new file mode 100644 index 0000000000..b644d3e992 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const duration = new Temporal.Duration(0, 1); +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dateAdd({ year: 2000, month: 5, day: 2, calendar: calendar2 }, duration); + +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/Calendar/prototype/dateAdd/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.js new file mode 100644 index 0000000000..44ba8d6c9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-temporal-object.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.calendar.prototype.dateadd +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dateadd step 4: + 4. Set _date_ to ? ToTemporalDate(_date_). + 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 calendar = new Temporal.Calendar("iso8601"); + const duration = new Temporal.Duration(0, 1); + calendar.dateAdd({ year: 2000, month: 5, day: 2, calendar: temporalObject }, duration); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..c3ef141dc7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/date-infinity-throws-rangeerror.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. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateadd +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const duration = new Temporal.Duration(1); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateAdd({ ...base, [prop]: inf }, duration, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dateAdd({ ...base, [prop]: obj }, duration, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js new file mode 100644 index 0000000000..e1b7dd7116 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/duration-argument-string-negative-fractional-units.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); + +const resultHours = calendar.dateAdd(instance, "-PT24.567890123H"); +TemporalHelpers.assertPlainDate(resultHours, 2000, 5, "M05", 1, "negative fractional hours"); + +const resultMinutes = calendar.dateAdd(instance, "-PT1440.567890123M"); +TemporalHelpers.assertPlainDate(resultMinutes, 2000, 5, "M05", 1, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/length.js new file mode 100644 index 0000000000..4e13716808 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateAdd, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/name.js new file mode 100644 index 0000000000..e32dfcf838 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd.name is "dateAdd". +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.Calendar.prototype.dateAdd, "name", { + value: "dateAdd", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/not-a-constructor.js new file mode 100644 index 0000000000..714fc59932 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: > + Temporal.Calendar.prototype.dateAdd 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.Calendar.prototype.dateAdd(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateAdd), false, + "isConstructor(Temporal.Calendar.prototype.dateAdd)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/options-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/options-object.js new file mode 100644 index 0000000000..5e083cbdf4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const result1 = instance.dateAdd(new Temporal.PlainDate(1976, 11, 18), new Temporal.Duration(1), {}); +TemporalHelpers.assertPlainDate( + result1, 1977, 11, "M11", 18, + "options may be an empty plain object" +); + +const result2 = instance.dateAdd(new Temporal.PlainDate(1976, 11, 18), new Temporal.Duration(1), () => {}); +TemporalHelpers.assertPlainDate( + result2, 1977, 11, "M11", 18, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.js new file mode 100644 index 0000000000..68f08ff73a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.dateAdd(new Temporal.PlainDate(1976, 11, 18), new Temporal.Duration(1), value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/order-of-operations.js new file mode 100644 index 0000000000..c1a3409489 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/order-of-operations.js @@ -0,0 +1,122 @@ +// |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.calendar.prototype.dateadd +description: Properties on an object passed to dateAdd() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + // ToTemporalDate → GetTemporalCalendarSlotValueWithISODefault + "get date.calendar", + "has date.calendar.dateAdd", + "has date.calendar.dateFromFields", + "has date.calendar.dateUntil", + "has date.calendar.day", + "has date.calendar.dayOfWeek", + "has date.calendar.dayOfYear", + "has date.calendar.daysInMonth", + "has date.calendar.daysInWeek", + "has date.calendar.daysInYear", + "has date.calendar.fields", + "has date.calendar.id", + "has date.calendar.inLeapYear", + "has date.calendar.mergeFields", + "has date.calendar.month", + "has date.calendar.monthCode", + "has date.calendar.monthDayFromFields", + "has date.calendar.monthsInYear", + "has date.calendar.weekOfYear", + "has date.calendar.year", + "has date.calendar.yearMonthFromFields", + "has date.calendar.yearOfWeek", + // lookup + "get date.calendar.dateFromFields", + "get date.calendar.fields", + // ToTemporalDate → CalendarFields + "call date.calendar.fields", + // ToTemporalDate → PrepareTemporalFields + "get date.day", + "get date.day.valueOf", + "call date.day.valueOf", + "get date.month", + "get date.month.valueOf", + "call date.month.valueOf", + "get date.monthCode", + "get date.monthCode.toString", + "call date.monthCode.toString", + "get date.year", + "get date.year.valueOf", + "call date.year.valueOf", + // ToTemporalDate → CalendarDateFromFields + "call date.calendar.dateFromFields", + // ToTemporalDuration + "get duration.days", + "get duration.days.valueOf", + "call duration.days.valueOf", + "get duration.hours", + "get duration.hours.valueOf", + "call duration.hours.valueOf", + "get duration.microseconds", + "get duration.microseconds.valueOf", + "call duration.microseconds.valueOf", + "get duration.milliseconds", + "get duration.milliseconds.valueOf", + "call duration.milliseconds.valueOf", + "get duration.minutes", + "get duration.minutes.valueOf", + "call duration.minutes.valueOf", + "get duration.months", + "get duration.months.valueOf", + "call duration.months.valueOf", + "get duration.nanoseconds", + "get duration.nanoseconds.valueOf", + "call duration.nanoseconds.valueOf", + "get duration.seconds", + "get duration.seconds.valueOf", + "call duration.seconds.valueOf", + "get duration.weeks", + "get duration.weeks.valueOf", + "call duration.weeks.valueOf", + "get duration.years", + "get duration.years.valueOf", + "call duration.years.valueOf", + // ToTemporalOverflow + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", +]; +const actual = []; + +const instance = new Temporal.Calendar("iso8601"); + +const date = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "date.calendar"), +}, "date"); + +const duration = TemporalHelpers.propertyBagObserver(actual, { + years: 1, + months: 2, + weeks: 3, + days: 4, + hours: 5, + minutes: 6, + seconds: 7, + milliseconds: 8, + microseconds: 9, + nanoseconds: 10, +}, "duration"); + +const options = TemporalHelpers.propertyBagObserver(actual, { overflow: "constrain" }, "options"); + +instance.dateAdd(date, duration, options); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js new file mode 100644 index 0000000000..fe288222f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.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.calendar.prototype.dateadd +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal, arrow-function] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(3, 3, 0, 3); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateAdd(date, duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.js new file mode 100644 index 0000000000..83728adf8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-undefined.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.calendar.prototype.dateadd +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 31, calendar); +const duration = new Temporal.Duration(3, 1); + +const explicit = calendar.dateAdd(date, duration, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2003, 6, "M06", 30, "default overflow is constrain"); +const implicit = calendar.dateAdd(date, duration, {}); +TemporalHelpers.assertPlainDate(implicit, 2003, 6, "M06", 30, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js new file mode 100644 index 0000000000..48da48d4a3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.calendar.prototype.dateadd step 7: + 7. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2, calendar); +const duration = new Temporal.Duration(3, 3, 0, 3); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.dateAdd(date, duration, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2003, 8, "M08", 5, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/prop-desc.js new file mode 100644 index 0000000000..72ef97adf8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +description: The "dateAdd" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateAdd, + "function", + "`typeof Calendar.prototype.dateAdd` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateAdd", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDate.js new file mode 100644 index 0000000000..9292f126ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDate.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd should throw from ToTemporalDate. +info: | + ... + 4. Set date to ? ToTemporalDate(date). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, + () => cal.dateAdd("invalid date string", new Temporal.Duration(1)), + 'cal.dateAdd("invalid date string", new Temporal.Duration(1)) throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDuration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDuration.js new file mode 100644 index 0000000000..4c4ae43502 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-range-error-from-ToTemporalDuration.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd should throw from ToTemporalDuration. +info: | + ... + 5. Set duration to ? ToTemporalDuration(duration). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, + () => cal.dateAdd("2020-02-03", "invalid duration string"), + 'cal.dateAdd("2020-02-03", "invalid duration string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-GetOptionsObject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-GetOptionsObject.js new file mode 100644 index 0000000000..c0a83de563 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/throw-type-error-from-GetOptionsObject.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: Temporal.Calendar.prototype.dateAdd should throw from GetOptionsObject. +info: | + ... + 6. Set options to ? GetOptionsObject(options). +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar('iso8601'); +let invalidOptionsList = [null, 'invalid option', 234, 23n, Symbol('foo'), true, false, Infinity]; + +invalidOptionsList.forEach(function(invalidOptions) { + assert.throws( + TypeError, + () => cal.dateAdd('2020-02-03', 'P1Y', invalidOptions), + 'cal.dateAdd("2020-02-03", "P1Y", invalidOptions) throws a TypeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/year-zero.js new file mode 100644 index 0000000000..4d9c53e388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateAdd/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.calendar.prototype.dateadd +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateAdd(arg, new Temporal.Duration()), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/branding.js new file mode 100644 index 0000000000..6758e0cdd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const dateFromFields = Temporal.Calendar.prototype.dateFromFields; + +assert.sameValue(typeof dateFromFields, "function"); + +const args = [{ year: 2000, month: 1, day: 1 }]; + +assert.throws(TypeError, () => dateFromFields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateFromFields.apply(null, args), "null"); +assert.throws(TypeError, () => dateFromFields.apply(true, args), "true"); +assert.throws(TypeError, () => dateFromFields.apply("", args), "empty string"); +assert.throws(TypeError, () => dateFromFields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateFromFields.apply(1, args), "1"); +assert.throws(TypeError, () => dateFromFields.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateFromFields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateFromFields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/builtin.js new file mode 100644 index 0000000000..f039b1d2cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: > + Tests that Temporal.Calendar.prototype.dateFromFields + 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.Calendar.prototype.dateFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.js new file mode 100644 index 0000000000..38475bb330 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/fields-not-object.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.calendar.prototype.datefromfields +description: Throw a TypeError if the fields is not an object +info: | + 4. If Type(_fields_) is not Object, throw a *TypeError* exception. +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Infinity, NaN, Math.PI, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws( + TypeError, + () => iso.dateFromFields(fields, {}) + `dateFromFields(${typeof fields}) throws a TypeError exception` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..3024c6466b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/infinity-throws-rangeerror.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. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.datefromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.dateFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dateFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/length.js new file mode 100644 index 0000000000..3c7ec630d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields.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.Calendar.prototype.dateFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/missing-properties.js new file mode 100644 index 0000000000..6a9ffd5dfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/missing-properties.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Errors due to missing properties on fields object are thrown in the correct order +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const missingDay = { + get year() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, + get month() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, + get monthCode() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, +}; +assert.throws(TypeError, () => instance.dateFromFields(missingDay), "day should be checked before year and month"); + +let getMonth = false; +let getMonthCode = false; +const missingYearAndMonth = { + day: 1, + get month() { + getMonth = true; + }, + get monthCode() { + getMonthCode = true; + }, +}; +assert.throws(TypeError, () => instance.dateFromFields(missingYearAndMonth), "year should be checked after fetching but before resolving the month"); +assert(getMonth, "year is fetched after month"); +assert(getMonthCode, "year is fetched after monthCode"); + +const missingMonth = { + day: 1, + year: 2000, +}; +assert.throws(TypeError, () => instance.dateFromFields(missingMonth), "month should be resolved last"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/name.js new file mode 100644 index 0000000000..f88fb05139 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields.name is "dateFromFields". +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.Calendar.prototype.dateFromFields, "name", { + value: "dateFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/not-a-constructor.js new file mode 100644 index 0000000000..bc9a9a78c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: > + Temporal.Calendar.prototype.dateFromFields 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.Calendar.prototype.dateFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateFromFields), false, + "isConstructor(Temporal.Calendar.prototype.dateFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/one-of-era-erayear-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/one-of-era-erayear-undefined.js new file mode 100644 index 0000000000..67d4befdce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/one-of-era-erayear-undefined.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.calendar.prototype.datefromfields +description: Does not throw a RangeError if only one of era/eraYear fields is present +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const base = { year: 2000, month: 5, day: 2, era: 'ce' }; +const instance = new Temporal.Calendar('iso8601'); +TemporalHelpers.assertPlainDate(instance.dateFromFields({ ...base }), 2000, 5, 'M05', 2); + +const base2 = { year: 2000, month: 5, day: 2, eraYear: 1 }; +TemporalHelpers.assertPlainDate(instance.dateFromFields({ ...base }), 2000, 5, 'M05', 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/options-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/options-object.js new file mode 100644 index 0000000000..2905c8ea94 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const result1 = instance.dateFromFields({ year: 1976, month: 11, day: 18 }, {}); +TemporalHelpers.assertPlainDate( + result1, 1976, 11, "M11", 18, + "options may be an empty plain object" +); + +const result2 = instance.dateFromFields({ year: 1976, month: 11, day: 18 }, () => {}); +TemporalHelpers.assertPlainDate( + result2, 1976, 11, "M11", 18, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.js new file mode 100644 index 0000000000..9193330fdd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +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.Calendar("iso8601"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.dateFromFields({ year: 1976, month: 11, day: 18 }, value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/order-of-operations.js new file mode 100644 index 0000000000..aff7bbdde3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/order-of-operations.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.calendar.prototype.datefromfields +description: Properties on objects passed to dateFromFields() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get fields.day", + "get fields.day.valueOf", + "call fields.day.valueOf", + "get fields.month", + "get fields.month.valueOf", + "call fields.month.valueOf", + "get fields.monthCode", + "get fields.monthCode.toString", + "call fields.monthCode.toString", + "get fields.year", + "get fields.year.valueOf", + "call fields.year.valueOf", + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", +]; +const actual = []; + +const instance = new Temporal.Calendar("iso8601"); + +const fields = TemporalHelpers.propertyBagObserver(actual, { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}, "fields"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + overflow: "reject", +}, "options"); + +const result = instance.dateFromFields(fields, options); +TemporalHelpers.assertPlainDate(result, 1, 1, "M01", 1, "date result"); +assert.sameValue(result.getISOFields().calendar, "iso8601", "calendar slot should store a string"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js new file mode 100644 index 0000000000..153e0361c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +features: [Temporal, arrow-function] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, + { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.js new file mode 100644 index 0000000000..3e4b9bb1d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-undefined.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.calendar.prototype.datefromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined }); +TemporalHelpers.assertPlainDate(explicit, 2000, 12, "M12", 2, "default overflow is constrain"); +const implicit = calendar.dateFromFields({ year: 2000, month: 15, day: 2 }, {}); +TemporalHelpers.assertPlainDate(implicit, 2000, 12, "M12", 2, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js new file mode 100644 index 0000000000..b75d4beb59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isodatefromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.datefromfields step 6: + 6. Let _result_ be ? ISODateFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainDate(result, 2000, 5, "M05", 2, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/prop-desc.js new file mode 100644 index 0000000000..50871e8d91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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.calendar.prototype.datefromfields +description: The "dateFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateFromFields, + "function", + "`typeof Calendar.prototype.dateFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/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/Calendar/prototype/dateFromFields/throw-type-error-from-GetOptionsObject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-GetOptionsObject.js new file mode 100644 index 0000000000..53393dae1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throw-type-error-from-GetOptionsObject.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields should throw TypeError from GetOptionsObject. +info: | + 4. If Type(fields) is not Object, throw a TypeError exception. +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar('iso8601'); + +let fields = { + year: 2021, + month: 7, + day: 20 +}; + +let notObjectList = [null, 'string', Symbol('efg'), true, false, Infinity, NaN, 123, 456n]; + +notObjectList.forEach(function(options) { + assert.throws( + TypeError, + () => cal.dateFromFields(fields, options), + 'cal.dateFromFields(fields, options) throws a TypeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js new file mode 100644 index 0000000000..3b11f18888 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-range-error.js @@ -0,0 +1,126 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: > + Temporal.Calendar.prototype.dateFromFields should throw RangeError for + input not in valid range. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601") + +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "m1", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "m1", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "M1", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "M1", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "m01", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "m01", day: 17}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 12, monthCode: "M11", day: 17}), + 'cal.dateFromFields({year: 2021, month: 12, monthCode: "M11", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "M00", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "M00", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "M19", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "M19", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "M99", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "M99", day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, monthCode: "M13", day: 17}), + 'cal.dateFromFields({year: 2021, monthCode: "M13", day: 17}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: -1, day: 17}), + 'cal.dateFromFields({year: 2021, month: -1, day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: -Infinity, day: 17}), + 'cal.dateFromFields({year: 2021, month: -Infinity, day: 17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 7, day: -17}), + 'cal.dateFromFields({year: 2021, month: 7, day: -17}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 7, day: -Infinity}), + 'cal.dateFromFields({year: 2021, month: 7, day: -Infinity}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 12, day: 0}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 12, day: 0}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 12, day: 32}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 12, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 1, day: 32}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 1, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 2, day: 29}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 2, day: 29}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 6, day: 31}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 6, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 9, day: 31}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 9, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 0, day: 5}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 0, day: 5}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields({year: 2021, month: 13, day: 5}, {overflow: "reject"}), + 'cal.dateFromFields({year: 2021, month: 13, day: 5}, {overflow: "reject"}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M12", day: 0}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M12", day: 0}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M12", day: 32}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M12", day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M01", day: 32}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M01", day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M02", day: 29}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M02", day: 29}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M06", day: 31}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M06", day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M09", day: 31}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M09", day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M00", day: 5}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M00", day: 5}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, monthCode: "M13", day: 5}, {overflow: "reject"}), + 'cal.dateFromFields( {year: 2021, monthCode: "M13", day: 5}, {overflow: "reject"}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 12, day: 0}), 'cal.dateFromFields( {year: 2021, month: 12, day: 0}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 0, day: 3}), 'cal.dateFromFields( {year: 2021, month: 0, day: 3}) throws a RangeError exception'); + +// Check throw for the second arg +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 7, day: 13}, {overflow: "invalid"}), 'cal.dateFromFields( {year: 2021, month: 7, day: 13}, {overflow: "invalid"}) throws a RangeError exception'); + +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 1, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 1, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 2, day: 29}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 2, day: 29}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 3, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 3, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 4, day: 31}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 4, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 5, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 5, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 6, day: 31}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 6, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 7, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 7, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 8, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 8, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 9, day: 31}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 9, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 10, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 10, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 11, day: 31}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 11, day: 31}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 12, day: 32}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 12, day: 32}, {overflow: "reject"}) throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateFromFields( + {year: 2021, month: 13, day: 5}, {overflow: "reject"}), 'cal.dateFromFields( {year: 2021, month: 13, day: 5}, {overflow: "reject"}) throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-type-error.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-type-error.js new file mode 100644 index 0000000000..83b69f4d9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/throws-type-error.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields should throw TypeError with wrong type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ +// Check throw for first arg +let cal = new Temporal.Calendar('iso8601'); +assert.throws(TypeError, () => cal.dateFromFields(), 'cal.dateFromFields() throws a TypeError exception'); + +[undefined, true, false, 123, 456n, Symbol(), 'string'].forEach(function(fields) { + assert.throws( + TypeError, + () => cal.dateFromFields(fields), + 'cal.dateFromFields(fields) throws a TypeError exception' + ); + + assert.throws( + TypeError, + () => cal.dateFromFields(fields, undefined), + 'cal.dateFromFields(fields, undefined) throws a TypeError exception' + ); + + assert.throws(TypeError, () => cal.dateFromFields(fields, { + overflow: 'constrain' + }), 'cal.dateFromFields(fields, {overflow: "constrain"}) throws a TypeError exception'); + + assert.throws(TypeError, () => cal.dateFromFields(fields, { + overflow: 'reject' + }), 'cal.dateFromFields(fields, {overflow: "reject"}) throws a TypeError exception'); +}); + +assert.throws(TypeError, () => cal.dateFromFields({ + month: 1, + day: 17 +}), 'cal.dateFromFields({month: 1, day: 17}) throws a TypeError exception'); + +assert.throws(TypeError, () => cal.dateFromFields({ + year: 2021, + day: 17 +}), 'cal.dateFromFields({year: 2021, day: 17}) throws a TypeError exception'); + +assert.throws(TypeError, () => cal.dateFromFields({ + year: 2021, + month: 12 +}), 'cal.dateFromFields({year: 2021, month: 12}) throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day-need-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day-need-constrain.js new file mode 100644 index 0000000000..d2e766146e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day-need-constrain.js @@ -0,0 +1,90 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields with year/month/day and need constrain +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601") + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 1, day: 133}), + 2021, 1, "M01", 31, + "year/month/day with day need to be constrained in Jan"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 2, day: 133}), + 2021, 2, "M02", 28, + "year/month/day with day need to be constrained in Feb"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 3, day: 133}), + 2021, 3, "M03", 31, + "year/month/day with day need to be constrained in March"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 4, day: 133}), + 2021, 4, "M04", 30, + "year/month/day with day need to be constrained in April"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 5, day: 133}), + 2021, 5, "M05", 31, + "year/month/day with day need to be constrained in May"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 6, day: 133}), + 2021, 6, "M06", 30, + "year/month/day with day need to be constrained in Jun"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 7, day: 133}), + 2021, 7, "M07", 31, + "year/month/day with day need to be constrained in July"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 8, day: 133}), + 2021, 8, "M08", 31, + "year/month/day with day need to be constrained in Aug"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 9, day: 133}), + 2021, 9, "M09", 30, + "year/month/day with day need to be constrained in Sept."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 10, day: 133}), + 2021, 10, "M10", 31, + "year/month/day with day need to be constrained in Oct."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 11, day: 133}), + 2021, 11, "M11", 30, + "year/month/day with day need to be constrained in Nov."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 12, day: 133}), + 2021, 12, "M12", 31, + "year/month/day with day need to be constrained in Dec."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 13, day: 500}), + 2021, 12, "M12", 31, + "year/month/day with month and day need to be constrained"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 999999, day: 500}), + 2021, 12, "M12", 31, + "year/month/day with month and day need to be constrained"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day.js new file mode 100644 index 0000000000..e24b574004 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-month-day.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields with year/month/day +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601") + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, month: 7, day: 15}), + 2021, 7, "M07", 15, + "year/month/day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day-need-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day-need-constrain.js new file mode 100644 index 0000000000..175c34a601 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day-need-constrain.js @@ -0,0 +1,80 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields with year, monthCode and day and need constrain +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601") + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M01", day: 133}), + 2021, 1, "M01", 31, + "year/monthCode/day with day need to be constrained in Jan"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M02", day: 133}), + 2021, 2, "M02", 28, + "year/monthCode/day with day need to be constrained in Feb"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M03", day: 133}), + 2021, 3, "M03", 31, + "year/monthCode/day with day need to be constrained in March"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M04", day: 133}), + 2021, 4, "M04", 30, + "year/monthCode/day with day need to be constrained in April"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M05", day: 133}), + 2021, 5, "M05", 31, + "year/monthCode/day with day need to be constrained in May"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M06", day: 133}), + 2021, 6, "M06", 30, + "year/monthCode/day with day need to be constrained in Jun"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M07", day: 133}), + 2021, 7, "M07", 31, + "year/monthCode/day with day need to be constrained in July"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M08", day: 133}), + 2021, 8, "M08", 31, + "year/monthCode/day with day need to be constrained in Aug"); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M09", day: 133}), + 2021, 9, "M09", 30, + "year/monthCode/day with day need to be constrained in Sept."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M10", day: 133}), + 2021, 10, "M10", 31, + "year/monthCode/day with day need to be constrained in Oct."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M11", day: 133}), + 2021, 11, "M11", 30, + "year/monthCode/day with day need to be constrained in Nov."); + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M12", day: 133}), + 2021, 12, "M12", 31, + "year/monthCode/day with day need to be constrained in Dec."); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day.js new file mode 100644 index 0000000000..ff07ed1935 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateFromFields/with-year-monthCode-day.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.datefromfields +description: Temporal.Calendar.prototype.dateFromFields with year, monthCode and day. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISODateFromFields(fields, options). + 7. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601") + +TemporalHelpers.assertPlainDate( + cal.dateFromFields({year: 2021, monthCode: "M07", day: 15}), + 2021, 7, "M07", 15, + "year/monthCode/day"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..ef09180179 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-builtin-calendar-no-array-iteration.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)); +instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..0385c15b1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-calendar-datefromfields-called-with-null-prototype-fields.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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +const arg1 = { year: 2000, month: 5, day: 2, calendar }; +const arg2 = new Temporal.PlainDate(1977, 11, 19); + +instance.dateUntil(arg1, arg2); +assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar (first argument)"); + +calendar.dateFromFieldsCallCount = 0; + +instance.dateUntil(arg2, arg1); +assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..1f24241be6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19))); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..5becde2c5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-duplicate-calendar-fields.js @@ -0,0 +1,20 @@ +// |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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19))); + assert.throws(RangeError, () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..5123301475 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-infinity-throws-rangeerror.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in a property bag for either argument is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.dateuntil +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2001, 6, 3); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dateUntil({ ...base, [prop]: inf }, other), `${prop} property cannot be ${inf}`); + + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls1 = []; + const obj1 = TemporalHelpers.toPrimitiveObserver(calls1, inf, prop); + assert.throws(RangeError, () => instance.dateUntil({ ...base, [prop]: obj1 }, other)); + assert.compareArray(calls1, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + + const calls2 = []; + const obj2 = TemporalHelpers.toPrimitiveObserver(calls2, inf, prop); + assert.throws(RangeError, () => instance.dateUntil(other, { ...base, [prop]: obj2 })); + assert.compareArray(calls2, [`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/Calendar/prototype/dateUntil/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-number.js new file mode 100644 index 0000000000..4a8ba0f55d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-number.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.calendar.prototype.dateuntil +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 18)), + "A number is not a valid ISO string for PlainDate (first argument)" + ); + assert.throws( + TypeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 18), arg), + "A number is not a valid ISO string for PlainDate (second argument)" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.js new file mode 100644 index 0000000000..526b151206 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-plaindatetime.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.calendar.prototype.dateuntil +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + 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] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 2); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const calendar = new Temporal.Calendar("iso8601"); + const result = calendar.dateUntil(datetime, date); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const calendar = new Temporal.Calendar("iso8601"); + const result = calendar.dateUntil(date, datetime); + assert.sameValue(result.total({ unit: "nanoseconds" }), 0, "time part dropped"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..89b104bb17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-case-insensitive.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.calendar.prototype.dateuntil +description: The calendar name is case-insensitive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result1 = instance.dateUntil(arg, new Temporal.PlainDate(1976, 11, 19)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "Calendar is case-insensitive (first argument)"); +const result2 = instance.dateUntil(new Temporal.PlainDate(1976, 11, 19), arg); +TemporalHelpers.assertDuration(result2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "Calendar is case-insensitive (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..712bf74a46 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Leap second is a valid ISO string for a calendar in a property bag +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result1 = instance.dateUntil(arg, new Temporal.PlainDate(1976, 11, 19)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "leap second is a valid ISO string for calendar (first argument)"); +const result2 = instance.dateUntil(new Temporal.PlainDate(1976, 11, 19), arg); +TemporalHelpers.assertDuration(result2, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "leap second is a valid ISO string for calendar (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..9d2fd6a583 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-number.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.calendar.prototype.dateuntil +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + "A number is not a valid ISO string for calendar (first argument)" + ); + assert.throws( + TypeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + "A number is not a valid ISO string for calendar (second argument)" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..037111eaa5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-string.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.calendar.prototype.dateuntil +description: A calendar ID is valid input for Calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +Object.defineProperty(instance, "dateFromFields", { + configurable: true, + enumerable: false, + get() { + TemporalHelpers.assertUnreachable("dateFromFields should not be looked up on receiver"); + }, +}); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + +const result1 = instance.dateUntil(arg, new Temporal.PlainDate(1976, 11, 18)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, `Calendar created from string "${arg} (first argument)"`); + +const result2 = instance.dateUntil(new Temporal.PlainDate(1976, 11, 18), arg); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, `Calendar created from string "${arg} (second argument)"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..245fbf46da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-wrong-type.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +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.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `${description} does not convert to a valid ISO string (first argument)` + ); + assert.throws( + typeof calendar === "string" ? RangeError : TypeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `${description} does not convert to a valid ISO string (second argument)` + ); +} + +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.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), `${description} is not a valid property bag and does not convert to a string (first argument)`); + assert.throws(TypeError, () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), `${description} is not a valid property bag and does not convert to a string (second argument)`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..117c3e627f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-propertybag-calendar-year-zero.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + "reject minus zero as extended year (first argument)" + ); + assert.throws( + RangeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + "reject minus zero as extended year (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..34e8f2c28c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19))); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..069f193cc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateUntil(arg, 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/Calendar/prototype/dateUntil/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..97efa5c7e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-critical-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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `reject unknown annotation with critical flag: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `reject unknown annotation with critical flag: ${arg} (second argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..47db3e2de7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-date-with-utc-offset.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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) { + TemporalHelpers.assertDuration( + instance.dateUntil(arg, arg), + 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.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `"${arg}" UTC offset without time is not valid for PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `"${arg}" UTC offset without time is not valid for PlainDate (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js new file mode 100644 index 0000000000..31c39e90a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js @@ -0,0 +1,70 @@ +// |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.calendar.prototype.dateuntil +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2020, 1, 1, instance); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateUntil(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..e8ba951085 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-calendar.js @@ -0,0 +1,37 @@ +// |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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `reject more than one calendar annotation if any critical: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `reject more than one calendar annotation if any critical: ${arg} (second argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..db2cbbf925 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-multiple-time-zone.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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `reject more than one time zone annotation: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `reject more than one time zone annotation: ${arg} (second argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-time-separators.js new file mode 100644 index 0000000000..06a8f07274 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-time-separators.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.calendar.prototype.dateuntil +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const date = new Temporal.PlainDate(2000, 5, 3); +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + TemporalHelpers.assertDuration( + instance.dateUntil(arg, date), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + `variant time separators (${description}), first argument` + ); + + TemporalHelpers.assertDuration( + instance.dateUntil(date, arg), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, + `variant time separators (${description}), second argument` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..66159880e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateUntil(arg, 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/Calendar/prototype/dateUntil/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..5f151e4bf8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dateUntil(arg, 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/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..2a7ae86b76 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-with-utc-designator.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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +const plainDate = new Temporal.PlainDate(2000, 5, 2); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dateUntil(arg, plainDate), + "String with UTC designator should not be valid as a PlainDate (first argument)" + ); + assert.throws( + RangeError, + () => instance.dateUntil(plainDate, arg), + "String with UTC designator should not be valid as a PlainDate (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-wrong-type.js new file mode 100644 index 0000000000..da9c257fc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-wrong-type.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainDate +features: [BigInt, Symbol, Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.Calendar("iso8601"); + +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.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), + `${description} does not convert to a valid ISO string (first argument)` + ); + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), + `${description} does not convert to a valid ISO string (second argument)` + ); +} + +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.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)), `${description} is not a valid property bag and does not convert to a string (first argument)`); + assert.throws(TypeError, () => instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg), `${description} is not a valid property bag and does not convert to a string (second argument)`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..6a09cb6ed5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-slots.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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.Calendar("iso8601"); +instance.dateUntil(arg, new Temporal.PlainDate(1977, 11, 19)); +instance.dateUntil(new Temporal.PlainDate(1977, 11, 19), arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..70c9fc1a12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.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.calendar.prototype.dateuntil +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 calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => calendar.dateUntil(datetime, date)); + assert.throws(RangeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..ebc1ebbf01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.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.calendar.prototype.dateuntil +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 calendar = new Temporal.Calendar("iso8601"); + 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, + () => calendar.dateUntil(datetime, date), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => calendar.dateUntil(date, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..ff81410145 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.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.calendar.prototype.dateuntil +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 calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(RangeError, () => calendar.dateUntil(datetime, date)); + assert.throws(RangeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..446a1a6ea3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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 calendar = new Temporal.Calendar("iso8601"); + const date = new Temporal.PlainDate(2000, 5, 2); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + + assert.throws(TypeError, () => calendar.dateUntil(datetime, date)); + assert.throws(TypeError, () => calendar.dateUntil(date, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js new file mode 100644 index 0000000000..99f4e9059b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/basic.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Basic tests for dateUntil(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const date1 = Temporal.PlainDate.from("1999-09-03"); +const date2 = Temporal.PlainDate.from("2000-01-01"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "two PlainDates"); + +TemporalHelpers.assertDuration( + iso.dateUntil(Temporal.PlainDateTime.from("1999-09-03T08:15:30"), date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: PlainDateTime"); + +TemporalHelpers.assertDuration( + iso.dateUntil({ year: 1999, month: 9, day: 3 }, date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: property bag"); + +TemporalHelpers.assertDuration( + iso.dateUntil("1999-09-03", date2, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "first argument: string"); + +assert.throws(TypeError, () => iso.dateUntil({ month: 11 }, date2, {}), "first argument: missing property"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, Temporal.PlainDateTime.from("2000-01-01T08:15:30"), {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: PlainDateTime"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, { year: 2000, month: 1, day: 1 }, {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: property bag"); + +TemporalHelpers.assertDuration( + iso.dateUntil(date1, "2000-01-01", {}), + 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, "second argument: string"); + +assert.throws(TypeError, () => iso.dateUntil(date1, { month: 11 }, {}), "second argument: missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/branding.js new file mode 100644 index 0000000000..ea4dec80e6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const dateUntil = Temporal.Calendar.prototype.dateUntil; + +assert.sameValue(typeof dateUntil, "function"); + +const args = [new Temporal.PlainDate(2021, 7, 16), new Temporal.PlainDate(2021, 7, 17)]; + +assert.throws(TypeError, () => dateUntil.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dateUntil.apply(null, args), "null"); +assert.throws(TypeError, () => dateUntil.apply(true, args), "true"); +assert.throws(TypeError, () => dateUntil.apply("", args), "empty string"); +assert.throws(TypeError, () => dateUntil.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dateUntil.apply(1, args), "1"); +assert.throws(TypeError, () => dateUntil.apply({}, args), "plain object"); +assert.throws(TypeError, () => dateUntil.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dateUntil.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/builtin.js new file mode 100644 index 0000000000..9cc12208df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: > + Tests that Temporal.Calendar.prototype.dateUntil + 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.Calendar.prototype.dateUntil), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dateUntil), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dateUntil), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dateUntil.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..cc19ddb323 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +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(); +calendar.dateUntil({ year: 2000, month: 5, day: 2, calendar }, { year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js new file mode 100644 index 0000000000..dc32b6b936 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-fields-iterable.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +const calendar3 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dateUntil( + { year: 2000, month: 5, day: 2, calendar: calendar2 }, + { year: 2005, month: 6, day: 3, calendar: calendar3 }, +); + +assert.sameValue(calendar1.fieldsCallCount, 0, "fields() method not called"); +assert.sameValue(calendar2.fieldsCallCount, 1, "fields() method called once"); +assert.sameValue(calendar3.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"); +assert.compareArray(calendar3.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar3.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js new file mode 100644 index 0000000000..a42cf66f0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-temporal-object.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dateuntil steps 4–5: + 4. Set _one_ to ? ToTemporalDate(_one_). + 5. Set _two_ to ? ToTemporalDate(_two_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.dateUntil( + { year: 2000, month: 5, day: 2, calendar: temporalObject }, + { year: 2005, month: 6, day: 3, calendar: temporalObject }, + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-day.js new file mode 100644 index 0000000000..5d5aaecbb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-day.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil with largestUnit is "day" +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). + 6. Set options to ? GetOptionsObject(options). + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). + 8. Let result be ! DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). + 9. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +["day", "days"].forEach(function(largestUnit) { + let opt = {largestUnit}; + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-16", opt), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "same day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-17", opt), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-17", opt), + 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, "32 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-09-16", opt), + 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, "62 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-16", opt), + 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, "365 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-07-16", opt), + 0, 0, 0, 3652, 0, 0, 0, 0, 0, 0, "3652 days"); + + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-17", "2021-07-16", opt), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "negative one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-17", "2021-07-16", opt), + 0, 0, 0, -32, 0, 0, 0, 0, 0, 0, "negative 32 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-09-16", "2021-07-16", opt), + 0, 0, 0, -62, 0, 0, 0, 0, 0, 0, "negative 62 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-16", "2021-07-16", opt), + 0, 0, 0, -365, 0, 0, 0, 0, 0, 0, "negative 365 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2031-07-16", "2021-07-16", opt), + 0, 0, 0, -3652, 0, 0, 0, 0, 0, 0, "negative 3652 days"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-month.js new file mode 100644 index 0000000000..127391dc73 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-month.js @@ -0,0 +1,97 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil with largestUnit is "month" +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). + 6. Set options to ? GetOptionsObject(options). + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). + 8. Let result be ! DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). + 9. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +["month", "months"].forEach(function(largestUnit) { + let opt = {largestUnit}; + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-16", opt), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "same day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-17", opt), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-23", opt), + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, "7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-16", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-12-16", "2021-01-16", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in different year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-05", "2021-02-05", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-07", "2021-03-07", opt), + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, "2 month in same year across Feb 28"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-17", opt), + 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, "1 month and 1 day in a month with 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-13", opt), + 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, "28 days roll across a month which has 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-09-16", opt), + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, "2 months with both months which have 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-16", opt), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, "12 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-07-16", opt), + 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, "120 months"); + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-17", "2021-07-16", opt), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "negative one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-23", "2021-07-16", opt), + 0, 0, 0, -7, 0, 0, 0, 0, 0, 0, "negative 7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-16", "2021-07-16", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-16", "2020-12-16", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in different year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-02-05", "2021-01-05", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-03-07", "2021-01-07", opt), + 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, "negative 2 month in same year across Feb 28"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-17", "2021-07-16", opt), + 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, "negative 1 month and 1 day in a month with 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-13", "2021-07-16", opt), + 0, 0, 0, -28, 0, 0, 0, 0, 0, 0, "negative 28 days roll across a month which has 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-09-16", "2021-07-16", opt), + 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, "negative 2 months with both months which have 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-16", "2021-07-16", opt), + 0, -12, 0, 0, 0, 0, 0, 0, 0, 0, "negative 12 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("2031-07-16", "2021-07-16", opt), + 0, -120, 0, 0, 0, 0, 0, 0, 0, 0, "negative 120 months"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-week.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-week.js new file mode 100644 index 0000000000..c3bf258482 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-week.js @@ -0,0 +1,74 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil with largestUnit is "week" +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). + 6. Set options to ? GetOptionsObject(options). + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). + 8. Let result be ! DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). + 9. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +["week", "weeks"].forEach(function(largestUnit) { + let opt = {largestUnit}; + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-16", opt), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "same day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-17", opt), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-23", opt), + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-16", opt), + 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, "4 weeks and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-13", opt), + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, "4 weeks"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-09-16", opt), + 0, 0, 8, 6, 0, 0, 0, 0, 0, 0, "8 weeks and 6 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-16", opt), + 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, "52 weeks and 1 day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-07-16", opt), + 0, 0, 521, 5, 0, 0, 0, 0, 0, 0, "521 weeks and 5 days"); + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-17", "2021-07-16", opt), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "negative one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-23", "2021-07-16", opt), + 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, "negative 7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-16", "2021-07-16", opt), + 0, 0, -4, -3, 0, 0, 0, 0, 0, 0, "negative 4 weeks and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-13", "2021-07-16", opt), + 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, "negative 4 weeks"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-09-16", "2021-07-16", opt), + 0, 0, -8, -6, 0, 0, 0, 0, 0, 0, "negative 8 weeks and 6 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-16", "2021-07-16", opt), + 0, 0, -52, -1, 0, 0, 0, 0, 0, 0, "negative 52 weeks and 1 day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2031-07-16", "2021-07-16", opt), + 0, 0, -521, -5, 0, 0, 0, 0, 0, 0, "negative 521 weeks and 5 days"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-year.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-year.js new file mode 100644 index 0000000000..fb29a8c493 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largest-unit-year.js @@ -0,0 +1,207 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil with largestUnit is "year" +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). + 6. Set options to ? GetOptionsObject(options). + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). + 8. Let result be ! DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). + 9. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +["year", "years"].forEach(function(largestUnit) { + let opt = {largestUnit}; + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-16", opt), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "same day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-17", opt), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-23", opt), + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, "7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-16", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-12-16", "2021-01-16", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in different year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-05", "2021-02-05", opt), + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, "1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-07", "2021-03-07", opt), + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, "2 month in same year across Feb 28"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-17", opt), + 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, "1 month and 1 day in a month with 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-13", opt), + 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, "28 days roll across a month which has 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-09-16", opt), + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, "2 months with both months which have 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-16", opt), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "1 year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-07-16", opt), + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, "10 years"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-19", opt), + 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, "1 year and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-09-19", opt), + 1, 2, 0, 3, 0, 0, 0, 0, 0, 0, "1 year 2 months and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-12-16", opt), + 10, 5, 0, 0, 0, 0, 0, 0, 0, 0, "10 years and 5 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("1997-12-16", "2021-07-16", opt), + 23, 7, 0, 0, 0, 0, 0, 0, 0, 0, "23 years and 7 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("1997-07-16", "2021-07-16", opt), + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, "24 years"); + TemporalHelpers.assertDuration( + cal.dateUntil("1997-07-16", "2021-07-15", opt), + 23, 11, 0, 29, 0, 0, 0, 0, 0, 0, "23 years, 11 months and 29 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("1997-06-16", "2021-06-15", opt), + 23, 11, 0, 30, 0, 0, 0, 0, 0, 0, "23 years, 11 months and 30 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("1960-02-16", "2020-03-16", opt), + 60, 1, 0, 0, 0, 0, 0, 0, 0, 0, "60 years, 1 month"); + TemporalHelpers.assertDuration( + cal.dateUntil("1960-02-16", "2021-03-15", opt), + 61, 0, 0, 27, 0, 0, 0, 0, 0, 0, "61 years, 27 days in non leap year"); + TemporalHelpers.assertDuration( + cal.dateUntil("1960-02-16", "2020-03-15", opt), + 60, 0, 0, 28, 0, 0, 0, 0, 0, 0, "60 years, 28 days in leap year"); + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-03-30", "2021-07-16", opt), + 0, 3, 0, 16, 0, 0, 0, 0, 0, 0, "3 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-03-30", "2021-07-16", opt), + 1, 3, 0, 16, 0, 0, 0, 0, 0, 0, "1 year, 3 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("1960-03-30", "2021-07-16", opt), + 61, 3, 0, 16, 0, 0, 0, 0, 0, 0, "61 years, 3 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2019-12-30", "2021-07-16", opt), + 1, 6, 0, 16, 0, 0, 0, 0, 0, 0, "1 year, 6 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-12-30", "2021-07-16", opt), + 0, 6, 0, 16, 0, 0, 0, 0, 0, 0, "6 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("1997-12-30", "2021-07-16", opt), + 23, 6, 0, 16, 0, 0, 0, 0, 0, 0, "23 years, 6 months and 16 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("0001-12-25", "2021-07-16", opt), + 2019, 6, 0, 21, 0, 0, 0, 0, 0, 0, "2019 years, 6 months and 21 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2019-12-30", "2021-03-05", opt), + 1, 2, 0, 5, 0, 0, 0, 0, 0, 0, "1 year, 2 months and 5 days"); + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-17", "2021-07-16", opt), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "negative one day"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-23", "2021-07-16", opt), + 0, 0, 0, -7, 0, 0, 0, 0, 0, 0, "negative 7 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-16", "2021-07-16", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-01-16", "2020-12-16", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in different year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-02-05", "2021-01-05", opt), + 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 month in same year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-03-07", "2021-01-07", opt), + 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, "negative 2 month in same year across Feb 28"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-17", "2021-07-16", opt), + 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, "negative 1 month and 1 day in a month with 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-13", "2021-07-16", opt), + 0, 0, 0, -28, 0, 0, 0, 0, 0, 0, "negative 28 days roll across a month which has 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-09-16", "2021-07-16", opt), + 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, "negative 2 months with both months which have 31 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-16", "2021-07-16", opt), + -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "negative 1 year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2031-07-16", "2021-07-16", opt), + -10, 0, 0, 0, 0, 0, 0, 0, 0, 0, "negative 10 years"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-19", "2021-07-16", opt), + -1, 0, 0, -3, 0, 0, 0, 0, 0, 0, "negative 1 year and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2022-09-19", "2021-07-16", opt), + -1, -2, 0, -3, 0, 0, 0, 0, 0, 0, "negative 1 year 2 months and 3 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2031-12-16", "2021-07-16", opt), + -10, -5, 0, 0, 0, 0, 0, 0, 0, 0, "negative 10 years and 5 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "1997-12-16", opt), + -23, -7, 0, 0, 0, 0, 0, 0, 0, 0, "negative 23 years and 7 months"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "1997-07-16", opt), + -24, 0, 0, 0, 0, 0, 0, 0, 0, 0, "negative 24 years"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-15", "1997-07-16", opt), + -23, -11, 0, -30, 0, 0, 0, 0, 0, 0, "negative 23 years, 11 months and 30 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-06-15", "1997-06-16", opt), + -23, -11, 0, -29, 0, 0, 0, 0, 0, 0, "negative 23 years, 11 months and 29 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-03-16", "1960-02-16", opt), + -60, -1, 0, 0, 0, 0, 0, 0, 0, 0, "negative 60 years, 1 month"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-03-15", "1960-02-16", opt), + -61, 0, 0, -28, 0, 0, 0, 0, 0, 0, "negative 61 years, 28 days in non leap year"); + TemporalHelpers.assertDuration( + cal.dateUntil("2020-03-15", "1960-02-16", opt), + -60, 0, 0, -28, 0, 0, 0, 0, 0, 0, "negative 60 years, 28 days in leap year"); + + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-03-30", opt), + 0, -3, 0, -17, 0, 0, 0, 0, 0, 0, "negative 3 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2020-03-30", opt), + -1, -3, 0, -17, 0, 0, 0, 0, 0, 0, "negative 1 year, 3 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "1960-03-30", opt), + -61, -3, 0, -17, 0, 0, 0, 0, 0, 0, "negative 61 years, 3 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2019-12-30", opt), + -1, -6, 0, -17, 0, 0, 0, 0, 0, 0, "negative 1 year, 6 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2020-12-30", opt), + 0, -6, 0, -17, 0, 0, 0, 0, 0, 0, "negative 6 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "1997-12-30", opt), + -23, -6, 0, -17, 0, 0, 0, 0, 0, 0, "negative 23 years, 6 months and 17 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "0001-12-25", opt), + -2019, -6, 0, -22, 0, 0, 0, 0, 0, 0, "negative 2019 years, 6 months and 22 days"); + TemporalHelpers.assertDuration( + cal.dateUntil("2021-03-05", "2019-12-30", opt), + -1, -2, 0, -6, 0, 0, 0, 0, 0, 0, "negative 1 year, 2 months and 6 days"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.js new file mode 100644 index 0000000000..097b975550 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/largestunit-plurals-accepted.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.calendar.prototype.dateuntil +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 calendar = new Temporal.Calendar("iso8601"); +const validUnits = [ + "year", + "month", + "week", + "day", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => calendar.dateUntil(earlier, later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/leap-second.js new file mode 100644 index 0000000000..e40554c226 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/leap-second.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.calendar.prototype.dateuntil +description: Leap second is a valid ISO string for PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +let result = instance.dateUntil(arg, new Temporal.PlainDate(2017, 1, 1)); +TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "leap second is a valid ISO string for PlainDate (first argument)"); +result = instance.dateUntil(new Temporal.PlainDate(2017, 1, 1), arg); +TemporalHelpers.assertDuration(result, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "leap second is a valid ISO string for PlainDate (second argument)"); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +result = instance.dateUntil(arg, new Temporal.PlainDate(2017, 1, 1)); +TemporalHelpers.assertDuration(result, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "second: 60 is ignored in property bag for PlainDate (first argument)"); +result = instance.dateUntil(new Temporal.PlainDate(2017, 1, 1), arg); +TemporalHelpers.assertDuration(result, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "second: 60 is ignored in property bag for PlainDate (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/length.js new file mode 100644 index 0000000000..03ccddfc49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.dateUntil, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/name.js new file mode 100644 index 0000000000..653e2aee58 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil.name is "dateUntil". +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.Calendar.prototype.dateUntil, "name", { + value: "dateUntil", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/no-options.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/no-options.js new file mode 100644 index 0000000000..76e14a3ca2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/no-options.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil with no options +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). + 6. Set options to ? GetOptionsObject(options). + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). + 8. Let result be ! DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit). + 9. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-16"), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "same day"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-07-17"), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "one day"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-08-17"), + 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, "32 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2021-09-16"), + 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, "62 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2022-07-16"), + 0, 0, 0, 365, 0, 0, 0, 0, 0, 0, "365 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-16", "2031-07-16"), + 0, 0, 0, 3652, 0, 0, 0, 0, 0, 0, "3652 days"); + + +TemporalHelpers.assertDuration( + cal.dateUntil("2021-07-17", "2021-07-16"), + 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, "negative one day"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-08-17", "2021-07-16"), + 0, 0, 0, -32, 0, 0, 0, 0, 0, 0, "negative 32 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2021-09-16", "2021-07-16"), + 0, 0, 0, -62, 0, 0, 0, 0, 0, 0, "negative 62 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2022-07-16", "2021-07-16"), + 0, 0, 0, -365, 0, 0, 0, 0, 0, 0, "negative 365 days"); +TemporalHelpers.assertDuration( + cal.dateUntil("2031-07-16", "2021-07-16"), + 0, 0, 0, -3652, 0, 0, 0, 0, 0, 0, "negative 3652 days"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/not-a-constructor.js new file mode 100644 index 0000000000..af2b9d1165 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: > + Temporal.Calendar.prototype.dateUntil 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.Calendar.prototype.dateUntil(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dateUntil), false, + "isConstructor(Temporal.Calendar.prototype.dateUntil)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/options-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/options-object.js new file mode 100644 index 0000000000..003988ef80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const result1 = instance.dateUntil(new Temporal.PlainDate(1976, 11, 18), new Temporal.PlainDate(1984, 5, 31), {}); +TemporalHelpers.assertDuration( + result1, 0, 0, 0, 2751, 0, 0, 0, 0, 0, 0, + "options may be an empty plain object" +); + +const result2 = instance.dateUntil(new Temporal.PlainDate(1976, 11, 18), new Temporal.PlainDate(1984, 5, 31), () => {}); +TemporalHelpers.assertDuration( + result2, 0, 0, 0, 2751, 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/Calendar/prototype/dateUntil/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/options-wrong-type.js new file mode 100644 index 0000000000..0bd2ca80fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +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.Calendar("iso8601"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.dateUntil(new Temporal.PlainDate(1976, 11, 18), new Temporal.PlainDate(1984, 5, 31), value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/order-of-operations.js new file mode 100644 index 0000000000..3daaaa71fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/order-of-operations.js @@ -0,0 +1,129 @@ +// |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.calendar.prototype.dateuntil +description: Properties on an object passed to dateUntil() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + // ToTemporalDate 1 → GetTemporalCalendarSlotValueWithISODefault + "get one.calendar", + "has one.calendar.dateAdd", + "has one.calendar.dateFromFields", + "has one.calendar.dateUntil", + "has one.calendar.day", + "has one.calendar.dayOfWeek", + "has one.calendar.dayOfYear", + "has one.calendar.daysInMonth", + "has one.calendar.daysInWeek", + "has one.calendar.daysInYear", + "has one.calendar.fields", + "has one.calendar.id", + "has one.calendar.inLeapYear", + "has one.calendar.mergeFields", + "has one.calendar.month", + "has one.calendar.monthCode", + "has one.calendar.monthDayFromFields", + "has one.calendar.monthsInYear", + "has one.calendar.weekOfYear", + "has one.calendar.year", + "has one.calendar.yearMonthFromFields", + "has one.calendar.yearOfWeek", + // lookup + "get one.calendar.dateFromFields", + "get one.calendar.fields", + // ToTemporalDate 1 → CalendarFields + "call one.calendar.fields", + // ToTemporalDate 1 → PrepareTemporalFields + "get one.day", + "get one.day.valueOf", + "call one.day.valueOf", + "get one.month", + "get one.month.valueOf", + "call one.month.valueOf", + "get one.monthCode", + "get one.monthCode.toString", + "call one.monthCode.toString", + "get one.year", + "get one.year.valueOf", + "call one.year.valueOf", + // ToTemporalDate 1 → CalendarDateFromFields + "call one.calendar.dateFromFields", + // ToTemporalDate 2 → GetTemporalCalendarSlotValueWithISODefault + "get two.calendar", + "has two.calendar.dateAdd", + "has two.calendar.dateFromFields", + "has two.calendar.dateUntil", + "has two.calendar.day", + "has two.calendar.dayOfWeek", + "has two.calendar.dayOfYear", + "has two.calendar.daysInMonth", + "has two.calendar.daysInWeek", + "has two.calendar.daysInYear", + "has two.calendar.fields", + "has two.calendar.id", + "has two.calendar.inLeapYear", + "has two.calendar.mergeFields", + "has two.calendar.month", + "has two.calendar.monthCode", + "has two.calendar.monthDayFromFields", + "has two.calendar.monthsInYear", + "has two.calendar.weekOfYear", + "has two.calendar.year", + "has two.calendar.yearMonthFromFields", + "has two.calendar.yearOfWeek", + // lookup + "get two.calendar.dateFromFields", + "get two.calendar.fields", + // ToTemporalDate 2 → CalendarFields + "call two.calendar.fields", + // ToTemporalDate 2 → PrepareTemporalFields + "get two.day", + "get two.day.valueOf", + "call two.day.valueOf", + "get two.month", + "get two.month.valueOf", + "call two.month.valueOf", + "get two.monthCode", + "get two.monthCode.toString", + "call two.monthCode.toString", + "get two.year", + "get two.year.valueOf", + "call two.year.valueOf", + // ToTemporalDate 2 → CalendarDateFromFields + "call two.calendar.dateFromFields", + // GetTemporalUnit + "get options.largestUnit", + "get options.largestUnit.toString", + "call options.largestUnit.toString", +]; +const actual = []; + +const instance = new Temporal.Calendar("iso8601"); + +const one = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 5, + monthCode: "M05", + day: 2, + calendar: TemporalHelpers.calendarObserver(actual, "one.calendar"), +}, "one"); + +const two = TemporalHelpers.propertyBagObserver(actual, { + year: 2001, + month: 10, + monthCode: "M10", + day: 4, + calendar: TemporalHelpers.calendarObserver(actual, "two.calendar"), +}, "two"); + +const options = TemporalHelpers.propertyBagObserver(actual, { largestUnit: "day" }, "options"); + +instance.dateUntil(one, two, options); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/prop-desc.js new file mode 100644 index 0000000000..ca1c358c89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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.calendar.prototype.dateuntil +description: The "dateUntil" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dateUntil, + "function", + "`typeof Calendar.prototype.dateUntil` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dateUntil", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/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/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js new file mode 100644 index 0000000000..1934d14874 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToLargestTemporalUnit.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil throw RangeError on ToLargestTemporalUnit with invalide or disallowed unit +info: | + 7. Let largestUnit be ? ToLargestTemporalUnit(options, « "hour", "minute", "second", "millisecond", "microsecond", "nanosecond" », "auto", "day"). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +["invalid", "hour", "minute", "second", "millisecond", "microsecond", + "nanosecond"].forEach(function(largestUnit) { + assert.throws(RangeError, () => cal.dateUntil("2021-07-16", "2022-03-04", {largestUnit}), + 'cal.dateUntil("2021-07-16", "2022-03-04", {largestUnit}) throws a RangeError exception'); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..f67da59b3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-range-error-ToTemporalDate.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil throw RangeError on ToTemporalDate +info: | + 1. Let calendar be the this value. + 4. Set one to ? ToTemporalDate(one). + 5. Set two to ? ToTemporalDate(two). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.dateUntil("2021-07-16", "invalide date"), + 'cal.dateUntil("2021-07-16", "invalide date") throws a RangeError exception'); +assert.throws(RangeError, () => cal.dateUntil("invalide date", "2021-07-16"), + 'cal.dateUntil("invalide date", "2021-07-16") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-GetOptionsObject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-GetOptionsObject.js new file mode 100644 index 0000000000..cb98140f26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/throws-type-error-GetOptionsObject.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: Temporal.Calendar.prototype.dateUntil throw TypeError on GetOptionsObject +info: | + 6. Set options to ? GetOptionsObject(options). +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar('iso8601'); + +['string', null, true, false, 123, 456n, Symbol(), Infinity, NaN].forEach(function(opt) { + assert.throws( + TypeError, + () => cal.dateUntil('2021-07-16', '2021-08-11', opt), + 'cal.dateUntil("2021-07-16", "2021-08-11", opt) throws a TypeError exception' + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.js new file mode 100644 index 0000000000..16009d4b8d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dateUntil/year-zero.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.calendar.prototype.dateuntil +description: Negative zero, as extended year, is invalid +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const date = new Temporal.PlainDate(2000, 5, 2); +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T00:45", + "-000000-10-31T00:45+01:00", + "-000000-10-31T00:45+00:00[UTC]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => calendar.dateUntil(arg, date), + "cannot use minus zero as extended date (first argument)" + ); + + assert.throws( + RangeError, + () => calendar.dateUntil(date, arg), + "cannot use minus zero as extended date (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..9b0728c95d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.day(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..7238a8789b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.day(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/Calendar/prototype/day/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..9ba373f078 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.day(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..4a285f17fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.day(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-leap-second.js new file mode 100644 index 0000000000..d8407aa8a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.day(arg); +assert.sameValue( + result1, + 31, + "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.day(arg); +assert.sameValue( + result2, + 31, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-number.js new file mode 100644 index 0000000000..131c280ca7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.day(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/Calendar/prototype/day/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..0879d4d819 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.day(arg); +assert.sameValue(result, 18, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..a1b5f9f765 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.day(arg); +assert.sameValue( + result, + 18, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..080af485a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.day(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..e397d5ede6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.day(arg); +assert.sameValue(result, 18, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..cef7b6ff05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + +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.day(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.day(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/Calendar/prototype/day/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..454c6a68de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..eaf3311eba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.day(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..2272f0dd1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.day(arg); + + assert.sameValue( + result, + 2, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..bbb53bca6a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..e6a0d706cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.day(arg); + + assert.sameValue( + result, + 2, + `"${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.day(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js new file mode 100644 index 0000000000..9b4cdb9bef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.day(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..15643ab93c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..3d84d9f531 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-separators.js new file mode 100644 index 0000000000..4fafb7248b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.day(arg); + + assert.sameValue( + result, + 2, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..e688ec555f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.day +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.day(arg); + + assert.sameValue( + result, + 2, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..7c98fe71e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.day(arg); + + assert.sameValue( + result, + 2, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..b1deda8354 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(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/Calendar/prototype/day/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-wrong-type.js new file mode 100644 index 0000000000..8e225e2bcb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + +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.day(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.day(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/Calendar/prototype/day/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..51bf0e2db4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.day(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..87f13d142c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +instance.day(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..7f3731cfd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..9809d9a0f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.day(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..71d7ae998a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..d9964911f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.day(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.js new file mode 100644 index 0000000000..710f903710 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/basic.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.calendar.prototype.day +description: Basic tests for day(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 5; +assert.sameValue(iso.day(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.day(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.day(Temporal.PlainMonthDay.from("11-05")), res, "PlainMonthDay"); +assert.sameValue(iso.day({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.day("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.day({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/branding.js new file mode 100644 index 0000000000..b77d8a8109 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const day = Temporal.Calendar.prototype.day; + +assert.sameValue(typeof day, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => day.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => day.apply(null, args), "null"); +assert.throws(TypeError, () => day.apply(true, args), "true"); +assert.throws(TypeError, () => day.apply("", args), "empty string"); +assert.throws(TypeError, () => day.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => day.apply(1, args), "1"); +assert.throws(TypeError, () => day.apply({}, args), "plain object"); +assert.throws(TypeError, () => day.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => day.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/builtin.js new file mode 100644 index 0000000000..5930579457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: > + Tests that Temporal.Calendar.prototype.day + 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.Calendar.prototype.day), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.day), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.day), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.day.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..46b9873fc8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +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(); +calendar.day({ 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/Calendar/prototype/day/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js new file mode 100644 index 0000000000..4410ec4006 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.day step 4: + 4. Return ? ISODay(_dateOrDateTime_). + sec-temporal-isoday step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.day({ year: 2000, month: 5, 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/Calendar/prototype/day/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js new file mode 100644 index 0000000000..b40cc5dcd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.day step 4: + 4. Return ? ISODay(_dateOrDateTime_). + sec-temporal-isoday step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.day({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js new file mode 100644 index 0000000000..d664a65afa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date-time.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day will take PlainDateTime and return + the value of the day. +info: | + 5. Return ! ISODay(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dateTime = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13) +assert.sameValue(cal.day(dateTime), 23, 'cal.day(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 23'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js new file mode 100644 index 0000000000..e78ca47b51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/date.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day will take PlainDate and return + the value of the day. +info: | + 5. Return ! ISODay(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let date = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.day(date), 15, 'cal.day(new Temporal.PlainDate(2021, 7, 15)) must return 15'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..0488591f63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.day({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.day({ ...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/Calendar/prototype/day/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/length.js new file mode 100644 index 0000000000..009a8695f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: Temporal.Calendar.prototype.day.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.Calendar.prototype.day, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js new file mode 100644 index 0000000000..b0f989774f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/month-day.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day will take PlainMonthDay and return + the value of the day. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISODay(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let monthDay = new Temporal.PlainMonthDay(7, 15); +assert.sameValue(cal.day(monthDay), 15, 'cal.day(new Temporal.PlainMonthDay(7, 15)) must return 15'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/name.js new file mode 100644 index 0000000000..81ecf1d75b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: Temporal.Calendar.prototype.day.name is "day". +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.Calendar.prototype.day, "name", { + value: "day", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/not-a-constructor.js new file mode 100644 index 0000000000..b754eb84c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day 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.Calendar.prototype.day(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.day), false, + "isConstructor(Temporal.Calendar.prototype.day)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/prop-desc.js new file mode 100644 index 0000000000..868d426d89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +description: The "day" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.day, + "function", + "`typeof Calendar.prototype.day` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "day", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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/Calendar/prototype/day/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js new file mode 100644 index 0000000000..9128672148 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/string.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day will take ISO8601 string and return + the value of the day. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISODay(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.day("2019-03-15"), 15, 'cal.day("2019-03-15") must return 15'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..1ea947ca9e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/throw-range-error-ToTemporalDate.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + Temporal.Calendar.prototype.day throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike + does not have an [[InitializedTemporalDate]] or + [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.day("invalid string"), + 'cal.day("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/year-zero.js new file mode 100644 index 0000000000..f1c0e19e8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/day/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.calendar.prototype.day +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.day(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..099a7b859b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.dayOfWeek(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..00120c596a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.dayOfWeek(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/Calendar/prototype/dayOfWeek/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..7839fb6454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dayOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..d492982e7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.dayOfWeek(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-leap-second.js new file mode 100644 index 0000000000..5f528093ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.dayOfWeek(arg); +assert.sameValue( + result1, + 6, + "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.dayOfWeek(arg); +assert.sameValue( + result2, + 6, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-number.js new file mode 100644 index 0000000000..6aa86300b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.dayOfWeek(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/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..afa01ac2f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfWeek(arg); +assert.sameValue(result, 4, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..014649fad0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfWeek(arg); +assert.sameValue( + result, + 4, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..8a041042d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.dayOfWeek(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..64a59dcc51 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfWeek(arg); +assert.sameValue(result, 4, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..ffd6082e3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + +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.dayOfWeek(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.dayOfWeek(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/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..767b87d15d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..efcd36bb13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dayOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..06f5075832 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfWeek(arg); + + assert.sameValue( + result, + 2, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..68aed5c169 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..bad099d0d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.dayOfWeek(arg); + + assert.sameValue( + result, + 2, + `"${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.dayOfWeek(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js new file mode 100644 index 0000000000..ce96c32afe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..0ac61801ab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..c1c244ac4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-separators.js new file mode 100644 index 0000000000..e53336a8d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfWeek(arg); + + assert.sameValue( + result, + 2, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..c802250c95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.dayofweek +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfWeek(arg); + + assert.sameValue( + result, + 2, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..e7a079cbc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfWeek(arg); + + assert.sameValue( + result, + 2, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..3a08fea3c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(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/Calendar/prototype/dayOfWeek/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-wrong-type.js new file mode 100644 index 0000000000..a1fdcb177e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + +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.dayOfWeek(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.dayOfWeek(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/Calendar/prototype/dayOfWeek/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..9b65728bd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.dayOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..e73205db91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +instance.dayOfWeek(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..fd111b05c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..83f279131c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dayOfWeek(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..ce4abc6ff1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..6a323edffb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dayOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.js new file mode 100644 index 0000000000..8bfdd06ac6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/basic.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.calendar.prototype.dayofweek +description: Basic tests for dayOfWeek(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 6; +assert.sameValue(iso.dayOfWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.dayOfWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.dayOfWeek({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.dayOfWeek("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.dayOfWeek({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/branding.js new file mode 100644 index 0000000000..5be07e2a66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const dayOfWeek = Temporal.Calendar.prototype.dayOfWeek; + +assert.sameValue(typeof dayOfWeek, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => dayOfWeek.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dayOfWeek.apply(null, args), "null"); +assert.throws(TypeError, () => dayOfWeek.apply(true, args), "true"); +assert.throws(TypeError, () => dayOfWeek.apply("", args), "empty string"); +assert.throws(TypeError, () => dayOfWeek.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dayOfWeek.apply(1, args), "1"); +assert.throws(TypeError, () => dayOfWeek.apply({}, args), "plain object"); +assert.throws(TypeError, () => dayOfWeek.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dayOfWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/builtin.js new file mode 100644 index 0000000000..8c4c4565c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: > + Tests that Temporal.Calendar.prototype.dayOfWeek + 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.Calendar.prototype.dayOfWeek), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dayOfWeek), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dayOfWeek), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dayOfWeek.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..a29e3f7263 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +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(); +calendar.dayOfWeek({ 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/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js new file mode 100644 index 0000000000..d608137f82 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dayofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dayOfWeek({ year: 2000, month: 5, 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/Calendar/prototype/dayOfWeek/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-temporal-object.js new file mode 100644 index 0000000000..68c013a000 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dayofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.dayOfWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..3ca706358b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dayOfWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dayOfWeek({ ...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/Calendar/prototype/dayOfWeek/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/length.js new file mode 100644 index 0000000000..0d2a913dcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: Temporal.Calendar.prototype.dayOfWeek.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.Calendar.prototype.dayOfWeek, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/name.js new file mode 100644 index 0000000000..f5b9970e0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: Temporal.Calendar.prototype.dayOfWeek.name is "dayOfWeek". +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.Calendar.prototype.dayOfWeek, "name", { + value: "dayOfWeek", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/not-a-constructor.js new file mode 100644 index 0000000000..9c78acd845 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: > + Temporal.Calendar.prototype.dayOfWeek 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.Calendar.prototype.dayOfWeek(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dayOfWeek), false, + "isConstructor(Temporal.Calendar.prototype.dayOfWeek)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js new file mode 100644 index 0000000000..9d039cbe62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date-time.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDateTime objects + and return the day of week. +info: | + 5. Return 𝔽(! ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dt = new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfWeek(dt), + 4, + 'cal.dayOfWeek(new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13)) must return 4' +); +dt = new Temporal.PlainDateTime(1996, 2, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfWeek(dt), + 5, + 'cal.dayOfWeek(new Temporal.PlainDateTime(1996, 2, 23, 5, 30, 13)) must return 5' +); +dt = new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfWeek(dt), + 7, + 'cal.dayOfWeek(new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13)) must return 7' +); +dt = new Temporal.PlainDateTime(1997, 6, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfWeek(dt), + 1, + 'cal.dayOfWeek(new Temporal.PlainDateTime(1997, 6, 23, 5, 30, 13)) must return 1' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js new file mode 100644 index 0000000000..4fbf36f474 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/plain-date.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Temporal.Calendar.prototype.dayOfWeek will take Temporal.PlainDate objects + and return the day of week. +info: | + 5. Return 𝔽(! ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let d = new Temporal.PlainDate(1970, 1, 1); +assert.sameValue(4, cal.dayOfWeek(d), '4 must return the same value returned by cal.dayOfWeek(d)'); +d = new Temporal.PlainDate(2021, 2, 15); +assert.sameValue(1, cal.dayOfWeek(d), '1 must return the same value returned by cal.dayOfWeek(d)'); +d = new Temporal.PlainDate(2021, 8, 15); +assert.sameValue(7, cal.dayOfWeek(d), '7 must return the same value returned by cal.dayOfWeek(d)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/prop-desc.js new file mode 100644 index 0000000000..a0b9027a05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +description: The "dayOfWeek" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dayOfWeek, + "function", + "`typeof Calendar.prototype.dayOfWeek` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dayOfWeek", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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/Calendar/prototype/dayOfWeek/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js new file mode 100644 index 0000000000..fe93ad4d4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/string.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + Temporal.Calendar.prototype.dayOfWeek will take ISO8601 string + and return the day of week. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.dayOfWeek("2019-01-18"), 5, 'cal.dayOfWeek("2019-01-18") must return 5'); +assert.sameValue(cal.dayOfWeek("2019-03-18"), 1, 'cal.dayOfWeek("2019-03-18") must return 1'); +assert.sameValue(cal.dayOfWeek("2019-05-18"), 6, 'cal.dayOfWeek("2019-05-18") must return 6'); +assert.sameValue(cal.dayOfWeek("2019-08-18"), 7, 'cal.dayOfWeek("2019-08-18") must return 7'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..6c435f930d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/throw-range-error-ToTemporalDate.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayOfWeek +description: > + Temporal.Calendar.prototype.dayOfWeek throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.dayOfWeek("invalid string"), + 'cal.dayOfWeek("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/year-zero.js new file mode 100644 index 0000000000..fadd2ebc31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.calendar.prototype.dayofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..dd7cea23e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.dayOfYear(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..9520c825bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.dayOfYear(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/Calendar/prototype/dayOfYear/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..559093bf44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dayOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..c8c47a6454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.dayOfYear(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-leap-second.js new file mode 100644 index 0000000000..d9dbd26e92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.dayOfYear(arg); +assert.sameValue( + result1, + 366, + "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.dayOfYear(arg); +assert.sameValue( + result2, + 366, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-number.js new file mode 100644 index 0000000000..b2c92dc6e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.dayOfYear(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/Calendar/prototype/dayOfYear/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..1123d096e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfYear(arg); +assert.sameValue(result, 323, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..ec673db6fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfYear(arg); +assert.sameValue( + result, + 323, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..bc418cddab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.dayOfYear(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..91ebe03687 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.dayOfYear(arg); +assert.sameValue(result, 323, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..7130706abb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + +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.dayOfYear(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.dayOfYear(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/Calendar/prototype/dayOfYear/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..7f06c31917 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..829564e665 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.dayOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..09956daf3a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfYear(arg); + + assert.sameValue( + result, + 123, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..48b3724340 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..445ee6aeff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.dayOfYear(arg); + + assert.sameValue( + result, + 123, + `"${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.dayOfYear(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js new file mode 100644 index 0000000000..37167a97d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..e8b2714c5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..38dc81a454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-separators.js new file mode 100644 index 0000000000..6399c49752 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfYear(arg); + + assert.sameValue( + result, + 123, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..e266fc22f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.dayofyear +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfYear(arg); + + assert.sameValue( + result, + 123, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..e7edf6df42 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.dayOfYear(arg); + + assert.sameValue( + result, + 123, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..e0ee9879bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(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/Calendar/prototype/dayOfYear/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-wrong-type.js new file mode 100644 index 0000000000..d607a28071 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + +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.dayOfYear(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.dayOfYear(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/Calendar/prototype/dayOfYear/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..fda318c39a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.dayOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..39bcc444b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +instance.dayOfYear(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..efbbd704cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..cca1006fd3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.dayOfYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..d9b51556fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..87c99d26c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.dayOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.js new file mode 100644 index 0000000000..b391523d47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/basic.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.calendar.prototype.dayofyear +description: Basic tests for dayOfYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 309; +assert.sameValue(iso.dayOfYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.dayOfYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.dayOfYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.dayOfYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.dayOfYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/branding.js new file mode 100644 index 0000000000..e20d743ae3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const dayOfYear = Temporal.Calendar.prototype.dayOfYear; + +assert.sameValue(typeof dayOfYear, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => dayOfYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => dayOfYear.apply(null, args), "null"); +assert.throws(TypeError, () => dayOfYear.apply(true, args), "true"); +assert.throws(TypeError, () => dayOfYear.apply("", args), "empty string"); +assert.throws(TypeError, () => dayOfYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => dayOfYear.apply(1, args), "1"); +assert.throws(TypeError, () => dayOfYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => dayOfYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => dayOfYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/builtin.js new file mode 100644 index 0000000000..8c5ea8047e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: > + Tests that Temporal.Calendar.prototype.dayOfYear + 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.Calendar.prototype.dayOfYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.dayOfYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.dayOfYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.dayOfYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..465e3b9c01 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +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(); +calendar.dayOfYear({ 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/Calendar/prototype/dayOfYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js new file mode 100644 index 0000000000..1d794405c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.dayofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.dayOfYear({ year: 2000, month: 5, 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/Calendar/prototype/dayOfYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-temporal-object.js new file mode 100644 index 0000000000..614b2cd72a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.dayofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.dayOfYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..9594bb6ded --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.dayOfYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.dayOfYear({ ...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/Calendar/prototype/dayOfYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/length.js new file mode 100644 index 0000000000..005e044216 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: Temporal.Calendar.prototype.dayOfYear.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.Calendar.prototype.dayOfYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/name.js new file mode 100644 index 0000000000..bc9dccc138 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: Temporal.Calendar.prototype.dayOfYear.name is "dayOfYear". +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.Calendar.prototype.dayOfYear, "name", { + value: "dayOfYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/not-a-constructor.js new file mode 100644 index 0000000000..b40bd8ee27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: > + Temporal.Calendar.prototype.dayOfYear 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.Calendar.prototype.dayOfYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.dayOfYear), false, + "isConstructor(Temporal.Calendar.prototype.dayOfYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js new file mode 100644 index 0000000000..58cc7d9670 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date-time.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Temporal.Calendar.prototype.dayOfYear will take PlainDateTime object and + return the day of year. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dt = new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 23, + 'cal.dayOfYear(new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13)) must return 23' +); + +dt = new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 54, + 'cal.dayOfYear(new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13)) must return 54' +); + +dt = new Temporal.PlainDateTime(1996, 3, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 83, + 'cal.dayOfYear(new Temporal.PlainDateTime(1996, 3, 23, 5, 30, 13)) must return 83' +); + +dt = new Temporal.PlainDateTime(1997, 3, 23, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 82, + 'cal.dayOfYear(new Temporal.PlainDateTime(1997, 3, 23, 5, 30, 13)) must return 82' +); + +dt = new Temporal.PlainDateTime(1997, 12, 31, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 365, + 'cal.dayOfYear(new Temporal.PlainDateTime(1997, 12, 31, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(1996, 12, 31, 5, 30, 13); +assert.sameValue( + cal.dayOfYear(dt), + 366, + 'cal.dayOfYear(new Temporal.PlainDateTime(1996, 12, 31, 5, 30, 13)) must return 366' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js new file mode 100644 index 0000000000..59ae28381a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/plain-date.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Temporal.Calendar.prototype.dayOfYear will take PlainDate object and + return the day of year. +info: | + 5. Return 𝔽(! ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let d = new Temporal.PlainDate(1970, 1, 1); +assert.sameValue(cal.dayOfYear(d), 1, 'cal.dayOfYear(new Temporal.PlainDate(1970, 1, 1)) must return 1'); +d = new Temporal.PlainDate(2000, 1, 1); +assert.sameValue(cal.dayOfYear(d), 1, 'cal.dayOfYear(new Temporal.PlainDate(2000, 1, 1)) must return 1'); + +d = new Temporal.PlainDate(2021, 1, 15); +assert.sameValue(cal.dayOfYear(d), 15, 'cal.dayOfYear(new Temporal.PlainDate(2021, 1, 15)) must return 15'); + +d = new Temporal.PlainDate(2020, 2, 15); +assert.sameValue(cal.dayOfYear(d), 46, 'cal.dayOfYear(new Temporal.PlainDate(2020, 2, 15)) must return 46'); + +d = new Temporal.PlainDate(2020, 3, 15); +assert.sameValue(cal.dayOfYear(d), 75, 'cal.dayOfYear(new Temporal.PlainDate(2020, 3, 15)) must return 75'); + +d = new Temporal.PlainDate(2000, 3, 15); +assert.sameValue(cal.dayOfYear(d), 75, 'cal.dayOfYear(new Temporal.PlainDate(2000, 3, 15)) must return 75'); + +d = new Temporal.PlainDate(2001, 3, 15); +assert.sameValue(cal.dayOfYear(d), 74, 'cal.dayOfYear(new Temporal.PlainDate(2001, 3, 15)) must return 74'); + +d = new Temporal.PlainDate(2000, 12, 31); +assert.sameValue(cal.dayOfYear(d), 366, 'cal.dayOfYear(new Temporal.PlainDate(2000, 12, 31)) must return 366'); + +d = new Temporal.PlainDate(2001, 12, 31); +assert.sameValue(cal.dayOfYear(d), 365, 'cal.dayOfYear(new Temporal.PlainDate(2001, 12, 31)) must return 365'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/prop-desc.js new file mode 100644 index 0000000000..36da5f9f97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +description: The "dayOfYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.dayOfYear, + "function", + "`typeof Calendar.prototype.dayOfYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "dayOfYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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/Calendar/prototype/dayOfYear/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js new file mode 100644 index 0000000000..1faed72a64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/string.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + Temporal.Calendar.prototype.dayOfYear will take ISO8601 string and + return the day of year. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue( + cal.dayOfYear("2019-01-18"), + 18, + 'cal.dayOfYear("2019-01-18") must return 18' +); +assert.sameValue( + cal.dayOfYear("2020-02-18"), + 49, + 'cal.dayOfYear("2020-02-18") must return 49' +); +assert.sameValue( + cal.dayOfYear("2019-12-31"), + 365, + 'cal.dayOfYear("2019-12-31") must return 365' +); +assert.sameValue( + cal.dayOfYear("2000-12-31"), + 366, + 'cal.dayOfYear("2000-12-31") must return 366' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..52080766e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/throw-range-error-ToTemporalDate.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.dayOfYear +description: > + Temporal.Calendar.prototype.dayOfYear throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.dayOfYear("invalid string"), + 'cal.dayOfYear("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/year-zero.js new file mode 100644 index 0000000000..27c08f65f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/dayOfYear/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.calendar.prototype.dayofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..319534ca4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.daysInMonth(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..1198405424 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.daysInMonth(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/Calendar/prototype/daysInMonth/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..50db14415b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInMonth(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..d183b4ee69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.daysInMonth(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-leap-second.js new file mode 100644 index 0000000000..30e56f42b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.daysInMonth(arg); +assert.sameValue( + result1, + 31, + "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.daysInMonth(arg); +assert.sameValue( + result2, + 31, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-number.js new file mode 100644 index 0000000000..e2f40427c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.daysInMonth(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/Calendar/prototype/daysInMonth/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..bcda4dbf08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInMonth(arg); +assert.sameValue(result, 30, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..bd6efd827b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInMonth(arg); +assert.sameValue( + result, + 30, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..4a2e0fe015 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.daysInMonth(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..8f207d8388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInMonth(arg); +assert.sameValue(result, 30, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..beb74d902f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + +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.daysInMonth(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.daysInMonth(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/Calendar/prototype/daysInMonth/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..8a6f651473 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..54de92486e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInMonth(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..4a0ed3ba9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInMonth(arg); + + assert.sameValue( + result, + 31, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..fd0f58ec15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..8a7a746a83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.daysInMonth(arg); + + assert.sameValue( + result, + 31, + `"${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.daysInMonth(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js new file mode 100644 index 0000000000..5d4b66354e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..a6b940ebf0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..5087ca2fe5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-separators.js new file mode 100644 index 0000000000..049dd56d85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInMonth(arg); + + assert.sameValue( + result, + 31, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..7432b240c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.daysinmonth +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInMonth(arg); + + assert.sameValue( + result, + 31, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..7b9329b45f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInMonth(arg); + + assert.sameValue( + result, + 31, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..2f221212ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(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/Calendar/prototype/daysInMonth/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-wrong-type.js new file mode 100644 index 0000000000..074c5479f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + +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.daysInMonth(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.daysInMonth(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/Calendar/prototype/daysInMonth/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..4d826cd5b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.daysInMonth(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..3ca0d6e1d4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +instance.daysInMonth(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..645308ec95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..8ed7f33ff2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInMonth(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..3ed66442c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..5c18bfdbcd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInMonth(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.js new file mode 100644 index 0000000000..85985cb146 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/basic.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.calendar.prototype.daysinmonth +description: Basic tests for daysInMonth(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 30; +assert.sameValue(iso.daysInMonth(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInMonth(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInMonth({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInMonth("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInMonth({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/branding.js new file mode 100644 index 0000000000..0a08a13ba8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const daysInMonth = Temporal.Calendar.prototype.daysInMonth; + +assert.sameValue(typeof daysInMonth, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInMonth.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInMonth.apply(null, args), "null"); +assert.throws(TypeError, () => daysInMonth.apply(true, args), "true"); +assert.throws(TypeError, () => daysInMonth.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInMonth.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInMonth.apply(1, args), "1"); +assert.throws(TypeError, () => daysInMonth.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInMonth.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInMonth.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/builtin.js new file mode 100644 index 0000000000..55e16b81a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: > + Tests that Temporal.Calendar.prototype.daysInMonth + 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.Calendar.prototype.daysInMonth), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInMonth), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInMonth), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInMonth.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..30931996c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +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(); +calendar.daysInMonth({ 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/Calendar/prototype/daysInMonth/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js new file mode 100644 index 0000000000..9ea5126443 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinmonth step 4.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInMonth({ year: 2000, month: 5, 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/Calendar/prototype/daysInMonth/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-temporal-object.js new file mode 100644 index 0000000000..00bad9889f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinmonth step 4.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.daysInMonth({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..eb47f7d645 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInMonth({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInMonth({ ...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/Calendar/prototype/daysInMonth/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/length.js new file mode 100644 index 0000000000..fe4acc1334 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: Temporal.Calendar.prototype.daysInMonth.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.Calendar.prototype.daysInMonth, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/name.js new file mode 100644 index 0000000000..6d65a4c15a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: Temporal.Calendar.prototype.daysInMonth.name is "daysInMonth". +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.Calendar.prototype.daysInMonth, "name", { + value: "daysInMonth", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/not-a-constructor.js new file mode 100644 index 0000000000..f7edc90848 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: > + Temporal.Calendar.prototype.daysInMonth 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.Calendar.prototype.daysInMonth(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInMonth), false, + "isConstructor(Temporal.Calendar.prototype.daysInMonth)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js new file mode 100644 index 0000000000..26e9a810fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date-time.js @@ -0,0 +1,116 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDateTime object + and return the number of days in that month. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slots, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dt = new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 1, 23, 5, 30, 13)) must return 31' +); + +// leap year +dt = new Temporal.PlainDateTime(1996, 2, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 29, + 'cal.daysInMonth(new Temporal.PlainDateTime(1996, 2, 23, 5, 30, 13)) must return 29' +); +dt = new Temporal.PlainDateTime(2000, 2, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 29, + 'cal.daysInMonth(new Temporal.PlainDateTime(2000, 2, 23, 5, 30, 13)) must return 29' +); + +// non leap year +dt = new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 28, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 2, 23, 5, 30, 13)) must return 28' +); + +dt = new Temporal.PlainDateTime(1997, 3, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 3, 23, 5, 30, 13)) must return 31' +); + +dt = new Temporal.PlainDateTime(1997, 4, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 30, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 4, 23, 5, 30, 13)) must return 30' +); + +dt = new Temporal.PlainDateTime(1997, 5, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 5, 23, 5, 30, 13)) must return 31' +); + +dt = new Temporal.PlainDateTime(1997, 6, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 30, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 6, 23, 5, 30, 13)) must return 30' +); + +dt = new Temporal.PlainDateTime(1997, 7, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 7, 23, 5, 30, 13)) must return 31' +); + +dt = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 31' +); + +dt = new Temporal.PlainDateTime(1997, 9, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 30, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 9, 23, 5, 30, 13)) must return 30' +); + +dt = new Temporal.PlainDateTime(1997, 10, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 10, 23, 5, 30, 13)) must return 31' +); + +dt = new Temporal.PlainDateTime(1997, 11, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 30, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 11, 23, 5, 30, 13)) must return 30' +); + +dt = new Temporal.PlainDateTime(1997, 12, 23, 5, 30, 13); +assert.sameValue( + cal.daysInMonth(dt), + 31, + 'cal.daysInMonth(new Temporal.PlainDateTime(1997, 12, 23, 5, 30, 13)) must return 31' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js new file mode 100644 index 0000000000..edb6f55093 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/plain-date.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Temporal.Calendar.prototype.daysInMonth will take Temporal.PlainDate object + and return the number of days in that month. +info: | + 5. Return 𝔽(! ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let d = new Temporal.PlainDate(2021, 1, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 1, 15)) must return 31'); + +// non-leap year +d = new Temporal.PlainDate(2021, 2, 15); +assert.sameValue(cal.daysInMonth(d), 28, 'cal.daysInMonth(new Temporal.PlainDate(2021, 2, 15)) must return 28'); + +// leap year +d = new Temporal.PlainDate(2020, 2, 15); +assert.sameValue(cal.daysInMonth(d), 29, 'cal.daysInMonth(new Temporal.PlainDate(2020, 2, 15)) must return 29'); +d = new Temporal.PlainDate(2000, 2, 15); +assert.sameValue(cal.daysInMonth(d), 29, 'cal.daysInMonth(new Temporal.PlainDate(2000, 2, 15)) must return 29'); + +d = new Temporal.PlainDate(2021, 3, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 3, 15)) must return 31'); + +d = new Temporal.PlainDate(2021, 4, 15); +assert.sameValue(cal.daysInMonth(d), 30, 'cal.daysInMonth(new Temporal.PlainDate(2021, 4, 15)) must return 30'); + +d = new Temporal.PlainDate(2021, 5, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 5, 15)) must return 31'); + +d = new Temporal.PlainDate(2021, 6, 15); +assert.sameValue(cal.daysInMonth(d), 30, 'cal.daysInMonth(new Temporal.PlainDate(2021, 6, 15)) must return 30'); + +d = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 7, 15)) must return 31'); + +d = new Temporal.PlainDate(2021, 8, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 8, 15)) must return 31'); + +d = new Temporal.PlainDate(2021, 9, 15); +assert.sameValue(cal.daysInMonth(d), 30, 'cal.daysInMonth(new Temporal.PlainDate(2021, 9, 15)) must return 30'); + +d = new Temporal.PlainDate(2021, 10, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 10, 15)) must return 31'); + +d = new Temporal.PlainDate(2021, 11, 15); +assert.sameValue(cal.daysInMonth(d), 30, 'cal.daysInMonth(new Temporal.PlainDate(2021, 11, 15)) must return 30'); + +d = new Temporal.PlainDate(2021, 12, 15); +assert.sameValue(cal.daysInMonth(d), 31, 'cal.daysInMonth(new Temporal.PlainDate(2021, 12, 15)) must return 31'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/prop-desc.js new file mode 100644 index 0000000000..d2f45ed5ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +description: The "daysInMonth" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInMonth, + "function", + "`typeof Calendar.prototype.daysInMonth` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInMonth", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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/Calendar/prototype/daysInMonth/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js new file mode 100644 index 0000000000..0f236a1622 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/string.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + Temporal.Calendar.prototype.daysInMonth will take ISO8601 string + and return the number of days in that month. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slots, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.daysInMonth("2019-01-18"), 31, 'cal.daysInMonth("2019-01-18") must return 31'); +// leap year +assert.sameValue(cal.daysInMonth("2020-02-18"), 29, 'cal.daysInMonth("2020-02-18") must return 29'); +// non leap +assert.sameValue(cal.daysInMonth("2019-02-18"), 28, 'cal.daysInMonth("2019-02-18") must return 28'); +assert.sameValue(cal.daysInMonth("2019-03-18"), 31, 'cal.daysInMonth("2019-03-18") must return 31'); +assert.sameValue(cal.daysInMonth("2019-04-18"), 30, 'cal.daysInMonth("2019-04-18") must return 30'); +assert.sameValue(cal.daysInMonth("2019-05-18"), 31, 'cal.daysInMonth("2019-05-18") must return 31'); +assert.sameValue(cal.daysInMonth("2019-06-18"), 30, 'cal.daysInMonth("2019-06-18") must return 30'); +assert.sameValue(cal.daysInMonth("2019-07-18"), 31, 'cal.daysInMonth("2019-07-18") must return 31'); +assert.sameValue(cal.daysInMonth("2019-08-18"), 31, 'cal.daysInMonth("2019-08-18") must return 31'); +assert.sameValue(cal.daysInMonth("2019-09-18"), 30, 'cal.daysInMonth("2019-09-18") must return 30'); +assert.sameValue(cal.daysInMonth("2019-10-18"), 31, 'cal.daysInMonth("2019-10-18") must return 31'); +assert.sameValue(cal.daysInMonth("2019-11-18"), 30, 'cal.daysInMonth("2019-11-18") must return 30'); +assert.sameValue(cal.daysInMonth("2019-12-18"), 31, 'cal.daysInMonth("2019-12-18") must return 31'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..6571d37f2d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/throw-range-error-ToTemporalDate.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysInMonth +description: > + Temporal.Calendar.prototype.daysInMonth throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slots, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.daysInMonth("invalid string"), + 'cal.daysInMonth("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/year-zero.js new file mode 100644 index 0000000000..7974098376 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInMonth/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.calendar.prototype.daysinmonth +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..110aed2bed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.daysInWeek(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..3db254da68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.daysInWeek(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/Calendar/prototype/daysInWeek/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..8952ae023f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..c36efdc0a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.daysInWeek(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-leap-second.js new file mode 100644 index 0000000000..aa15290d2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.daysInWeek(arg); +assert.sameValue( + result1, + 7, + "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.daysInWeek(arg); +assert.sameValue( + result2, + 7, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-number.js new file mode 100644 index 0000000000..a279f5c8c2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.daysInWeek(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/Calendar/prototype/daysInWeek/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..08a615e309 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInWeek(arg); +assert.sameValue(result, 7, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..0a2b0806f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInWeek(arg); +assert.sameValue( + result, + 7, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..f4f77d8c2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.daysInWeek(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..556f29d81f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInWeek(arg); +assert.sameValue(result, 7, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..11394edbb6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + +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.daysInWeek(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.daysInWeek(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/Calendar/prototype/daysInWeek/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..7d8395c074 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..cda32b22e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..25f5900218 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInWeek(arg); + + assert.sameValue( + result, + 7, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..54755595a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..74ece3cf77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.daysInWeek(arg); + + assert.sameValue( + result, + 7, + `"${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.daysInWeek(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js new file mode 100644 index 0000000000..c748c767a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..57ba7d4c4a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..fc99e1a45a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-separators.js new file mode 100644 index 0000000000..1059a26053 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInWeek(arg); + + assert.sameValue( + result, + 7, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..9716308c3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.daysinweek +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInWeek(arg); + + assert.sameValue( + result, + 7, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..d5ce3102a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInWeek(arg); + + assert.sameValue( + result, + 7, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..5ba18b0ea1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(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/Calendar/prototype/daysInWeek/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-wrong-type.js new file mode 100644 index 0000000000..449bb99be3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + +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.daysInWeek(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.daysInWeek(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/Calendar/prototype/daysInWeek/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..941c35db81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.daysInWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..60a3547c9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +instance.daysInWeek(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..6145e1b1f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..10c6de0f88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInWeek(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..a2700dd325 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..575f44a56f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.js new file mode 100644 index 0000000000..bc08c6bcd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/basic.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.calendar.prototype.daysinweek +description: Basic tests for daysInWeek(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 7; +assert.sameValue(iso.daysInWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInWeek({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInWeek("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInWeek({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/branding.js new file mode 100644 index 0000000000..6772299fda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const daysInWeek = Temporal.Calendar.prototype.daysInWeek; + +assert.sameValue(typeof daysInWeek, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInWeek.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInWeek.apply(null, args), "null"); +assert.throws(TypeError, () => daysInWeek.apply(true, args), "true"); +assert.throws(TypeError, () => daysInWeek.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInWeek.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInWeek.apply(1, args), "1"); +assert.throws(TypeError, () => daysInWeek.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInWeek.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/builtin.js new file mode 100644 index 0000000000..d0cdf2e2ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: > + Tests that Temporal.Calendar.prototype.daysInWeek + 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.Calendar.prototype.daysInWeek), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInWeek), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInWeek), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInWeek.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..1c31202345 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +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(); +calendar.daysInWeek({ 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/Calendar/prototype/daysInWeek/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js new file mode 100644 index 0000000000..5fe4eb09bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinweek step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInWeek({ year: 2000, month: 5, 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/Calendar/prototype/daysInWeek/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-temporal-object.js new file mode 100644 index 0000000000..98d7a71412 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinweek step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.daysInWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date-time.js new file mode 100644 index 0000000000..7ab14c3ca8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date-time.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinweeks +description: Temporal.Calendar.prototype.daysInWeek will take PlainDateTime and return 7. +info: | + 4. Perform ? ToTemporalDate(temporalDateLike). + 5. Return 7𝔽. +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dt = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInWeek(dt), + 7, + 'cal.daysInWeek(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 7' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date.js new file mode 100644 index 0000000000..62f2ff263a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/date.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinweeks +description: Temporal.Calendar.prototype.daysInWeek will take PlainDate and return 7. +info: | + 5. Return 7𝔽. +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let d = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.daysInWeek(d), 7, 'cal.daysInWeek(new Temporal.PlainDate(2021, 7, 15)) must return 7'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..44cecb2e90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInWeek({ ...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/Calendar/prototype/daysInWeek/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/length.js new file mode 100644 index 0000000000..b29774e9ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: Temporal.Calendar.prototype.daysInWeek.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.Calendar.prototype.daysInWeek, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/name.js new file mode 100644 index 0000000000..59cfe96553 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: Temporal.Calendar.prototype.daysInWeek.name is "daysInWeek". +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.Calendar.prototype.daysInWeek, "name", { + value: "daysInWeek", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/not-a-constructor.js new file mode 100644 index 0000000000..3445a89301 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: > + Temporal.Calendar.prototype.daysInWeek 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.Calendar.prototype.daysInWeek(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInWeek), false, + "isConstructor(Temporal.Calendar.prototype.daysInWeek)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/prop-desc.js new file mode 100644 index 0000000000..27bc5aca22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +description: The "daysInWeek" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInWeek, + "function", + "`typeof Calendar.prototype.daysInWeek` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInWeek", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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/Calendar/prototype/daysInWeek/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js new file mode 100644 index 0000000000..b7ca1084a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/string.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinweeks +description: > + Temporal.Calendar.prototype.daysInWeek will take valid ISO8601 string + and return 7. +info: | + 4. Perform ? ToTemporalDate(temporalDateLike). + 5. Return 7𝔽. +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); +assert.sameValue(cal.daysInWeek("2019-03-18"), 7, 'cal.daysInWeek("2019-03-18") must return 7'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..7bd6692848 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/throw-range-error-ToTemporalDate.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysInWeek +description: > + Temporal.Calendar.prototype.daysInWeek throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.daysInWeek("invalid string"), + 'cal.daysInWeek("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/year-zero.js new file mode 100644 index 0000000000..bdd058fe7a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInWeek/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.calendar.prototype.daysinweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..a1a9d56b40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.daysInYear(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..b7d705dff3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.daysInYear(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/Calendar/prototype/daysInYear/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..f47b077c13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..8600467296 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.daysInYear(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-leap-second.js new file mode 100644 index 0000000000..7ea0a919f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.daysInYear(arg); +assert.sameValue( + result1, + 366, + "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.daysInYear(arg); +assert.sameValue( + result2, + 366, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-number.js new file mode 100644 index 0000000000..a4192c3a91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.daysInYear(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/Calendar/prototype/daysInYear/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..762b02f555 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInYear(arg); +assert.sameValue(result, 366, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..a491924c6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInYear(arg); +assert.sameValue( + result, + 366, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..99a8086ff6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.daysInYear(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..c1c2e5a742 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.daysInYear(arg); +assert.sameValue(result, 366, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..b259e17cb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + +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.daysInYear(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.daysInYear(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/Calendar/prototype/daysInYear/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..18d81a4c17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..19af1a4da4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.daysInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..bd1c76b3d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInYear(arg); + + assert.sameValue( + result, + 366, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..4a4ce08fcf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..b5cf28d12d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.daysInYear(arg); + + assert.sameValue( + result, + 366, + `"${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.daysInYear(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js new file mode 100644 index 0000000000..e26385f3ba --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..5b8160db1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..37f4be64b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-separators.js new file mode 100644 index 0000000000..d5b474c4ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInYear(arg); + + assert.sameValue( + result, + 366, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..be37b75348 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.daysinyear +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInYear(arg); + + assert.sameValue( + result, + 366, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..56f5429ea1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.daysInYear(arg); + + assert.sameValue( + result, + 366, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..0c09cafed0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(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/Calendar/prototype/daysInYear/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-wrong-type.js new file mode 100644 index 0000000000..d74e334fb7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + +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.daysInYear(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.daysInYear(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/Calendar/prototype/daysInYear/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..3788acb0b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.daysInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..806c8a0da8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +instance.daysInYear(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..27c987cc47 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..ba08e54bc6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.daysInYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..f393a863b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..70ce4d3e49 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.daysInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.js new file mode 100644 index 0000000000..75c610132f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/basic.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.calendar.prototype.daysinyear +description: Basic tests for daysInYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 365; +assert.sameValue(iso.daysInYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.daysInYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.daysInYear(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.daysInYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.daysInYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.daysInYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/branding.js new file mode 100644 index 0000000000..803d4ac8c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const daysInYear = Temporal.Calendar.prototype.daysInYear; + +assert.sameValue(typeof daysInYear, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => daysInYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => daysInYear.apply(null, args), "null"); +assert.throws(TypeError, () => daysInYear.apply(true, args), "true"); +assert.throws(TypeError, () => daysInYear.apply("", args), "empty string"); +assert.throws(TypeError, () => daysInYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => daysInYear.apply(1, args), "1"); +assert.throws(TypeError, () => daysInYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => daysInYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => daysInYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/builtin.js new file mode 100644 index 0000000000..32cbf094c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: > + Tests that Temporal.Calendar.prototype.daysInYear + 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.Calendar.prototype.daysInYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.daysInYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.daysInYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.daysInYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..7d7c2c34ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +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(); +calendar.daysInYear({ 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/Calendar/prototype/daysInYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js new file mode 100644 index 0000000000..8c09cdeb78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.daysinyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.daysInYear({ year: 2000, month: 5, 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/Calendar/prototype/daysInYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js new file mode 100644 index 0000000000..47db820adf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.daysinyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.daysInYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..5c3b5b8bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.daysInYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.daysInYear({ ...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/Calendar/prototype/daysInYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/length.js new file mode 100644 index 0000000000..abf641692b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: Temporal.Calendar.prototype.daysInYear.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.Calendar.prototype.daysInYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/name.js new file mode 100644 index 0000000000..62a1d4ca2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: Temporal.Calendar.prototype.daysInYear.name is "daysInYear". +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.Calendar.prototype.daysInYear, "name", { + value: "daysInYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/not-a-constructor.js new file mode 100644 index 0000000000..a601f0132a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: > + Temporal.Calendar.prototype.daysInYear 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.Calendar.prototype.daysInYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.daysInYear), false, + "isConstructor(Temporal.Calendar.prototype.daysInYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js new file mode 100644 index 0000000000..8782edd51b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date-time.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDateTime and return + the number of days in a year. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ISODaysInYear(temporalDateLike.[[ISOYear]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dt = new Temporal.PlainDateTime(1995, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(1995, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(1996, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 366, + 'cal.daysInYear(new Temporal.PlainDateTime(1996, 8, 23, 5, 30, 13)) must return 366' +); + +dt = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(1998, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(1998, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(1999, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(1999, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(2000, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 366, + 'cal.daysInYear(new Temporal.PlainDateTime(2000, 8, 23, 5, 30, 13)) must return 366' +); + +dt = new Temporal.PlainDateTime(2001, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(2001, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(2002, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(2002, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(2003, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(2003, 8, 23, 5, 30, 13)) must return 365' +); + +dt = new Temporal.PlainDateTime(2004, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 366, + 'cal.daysInYear(new Temporal.PlainDateTime(2004, 8, 23, 5, 30, 13)) must return 366' +); + +dt = new Temporal.PlainDateTime(2005, 8, 23, 5, 30, 13); +assert.sameValue( + cal.daysInYear(dt), + 365, + 'cal.daysInYear(new Temporal.PlainDateTime(2005, 8, 23, 5, 30, 13)) must return 365' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js new file mode 100644 index 0000000000..54b3383c1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/plain-date.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDate and return + the number of days in a year. +info: | + 5. Return 𝔽(! ISODaysInYear(temporalDateLike.[[ISOYear]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let d = new Temporal.PlainDate(1995, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(1995, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(1996, 7, 15); +assert.sameValue(cal.daysInYear(d), 366, 'cal.daysInYear(new Temporal.PlainDate(1996, 7, 15)) must return 366'); + +d = new Temporal.PlainDate(1997, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(1997, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(1998, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(1998, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(1999, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(1999, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(2000, 7, 15); +assert.sameValue(cal.daysInYear(d), 366, 'cal.daysInYear(new Temporal.PlainDate(2000, 7, 15)) must return 366'); + +d = new Temporal.PlainDate(2001, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(2001, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(2002, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(2002, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(2003, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(2003, 7, 15)) must return 365'); + +d = new Temporal.PlainDate(2004, 7, 15); +assert.sameValue(cal.daysInYear(d), 366, 'cal.daysInYear(new Temporal.PlainDate(2004, 7, 15)) must return 366'); + +d = new Temporal.PlainDate(2005, 7, 15); +assert.sameValue(cal.daysInYear(d), 365, 'cal.daysInYear(new Temporal.PlainDate(2005, 7, 15)) must return 365'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/prop-desc.js new file mode 100644 index 0000000000..77e93a567c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +description: The "daysInYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.daysInYear, + "function", + "`typeof Calendar.prototype.daysInYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "daysInYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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/Calendar/prototype/daysInYear/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js new file mode 100644 index 0000000000..f1697e8fc9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/string.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + Temporal.Calendar.prototype.daysInYear will take PlainDate and return + the number of days in a year. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ISODaysInYear(temporalDateLike.[[ISOYear]])). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.daysInYear("2019-03-18"), 365, 'cal.daysInYear("2019-03-18") must return 365'); +assert.sameValue(cal.daysInYear("2020-03-18"), 366, 'cal.daysInYear("2020-03-18") must return 366'); +assert.sameValue(cal.daysInYear("2021-03-18"), 365, 'cal.daysInYear("2021-03-18") must return 365'); +assert.sameValue(cal.daysInYear("2022-03-18"), 365, 'cal.daysInYear("2022-03-18") must return 365'); +assert.sameValue(cal.daysInYear("2023-03-18"), 365, 'cal.daysInYear("2023-03-18") must return 365'); +assert.sameValue(cal.daysInYear("2024-03-18"), 366, 'cal.daysInYear("2024-03-18") must return 366'); +assert.sameValue(cal.daysInYear("2025-03-18"), 365, 'cal.daysInYear("2025-03-18") must return 365'); +assert.sameValue(cal.daysInYear("2026-03-18"), 365, 'cal.daysInYear("2026-03-18") must return 365'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..40fff73941 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/throw-range-error-ToTemporalDate.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.calendar.prototype.daysInYear +description: > + Temporal.Calendar.prototype.daysInYear throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does + not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] + internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.daysInYear("invalid string"), + 'cal.daysInYear("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/year-zero.js new file mode 100644 index 0000000000..8fd8c110a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/daysInYear/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.calendar.prototype.daysinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.js new file mode 100644 index 0000000000..ead494c99e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-iterable-not-array.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.calendar.prototype.fields +description: A non-Array iterable passed as the argument is exhausted +info: | + sec-temporal.calendar.prototype.fields step 4: + 4. Let _fieldNames_ be ? IterableToList(_fields_). +includes: [compareArray.js] +features: [Temporal] +---*/ + +const fieldNames = ["day", "month", "monthCode", "year"]; +const iterable = { + iteratorExhausted: false, + *[Symbol.iterator]() { + yield* fieldNames; + this.iteratorExhausted = true; + }, +}; + +const calendar = new Temporal.Calendar("iso8601"); +const result = calendar.fields(iterable); + +assert.compareArray(result, fieldNames); +assert(iterable.iteratorExhausted); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js new file mode 100644 index 0000000000..be868d3bf7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-duplicate-keys.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Duplicate fields are not allowed in the argument to Calendar.prototype.fields +info: | + sec-temporal.calendar.prototype.fields step 7.b.iii: + iii. If _fieldNames_ contains _nextValue_, then + 1. Let _completion_ be ThrowCompletion(a newly created *RangeError* object). + 2. Return ? IteratorClose(_iteratorRecord_, _completion_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +assert.throws(RangeError, () => calendar.fields(["day", "month", "day"])); +assert.throws(RangeError, () => calendar.fields(["year", "month", "monthCode", "day", "year"])); + +const manyFields = { + count: 0 +}; + +manyFields[Symbol.iterator] = function*() { + while (this.count++ < 100) yield "year"; +}; + +assert.throws(RangeError, () => calendar.fields(manyFields), "Rejected duplicate values"); +assert.sameValue(manyFields.count, 2, "Rejected first duplicate value"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js new file mode 100644 index 0000000000..81bc2e5d64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/argument-throws-invalid-keys.js @@ -0,0 +1,46 @@ +// |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.calendar.prototype.fields +description: > + Calendar.prototype.fields rejects input field names that are not singular + names of Temporal date units +info: | + sec-temporal.calendar.prototype.fields step 7.b.ii: + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + ii. If Type(nextValue) is not String, then + 1. Let completion be ThrowCompletion(a newly created TypeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). + sec-temporal.calendar.prototype.fields step 7.b.iv: + iv. If _nextValue_ is not one of *"year"*, *"month"*, *"monthCode"*, or *"day"*, then + 1. Let _completion_ be ThrowCompletion(a newly created *RangeError* object). + 2. Return ? IteratorClose(_iteratorRecord_, _completion_). + +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +assert.throws(TypeError, () => calendar.fields([1])); +assert.throws(TypeError, () => calendar.fields([1n])); +assert.throws(TypeError, () => calendar.fields([Symbol('foo')])); +assert.throws(TypeError, () => calendar.fields([true])); +assert.throws(TypeError, () => calendar.fields([null])); +assert.throws(TypeError, () => calendar.fields([{}])); +assert.throws(TypeError, () => calendar.fields([undefined])); +assert.throws(TypeError, () => calendar.fields(["day", 1])); +assert.throws(RangeError, () => calendar.fields(["hour"])); +assert.throws(RangeError, () => calendar.fields(["minute"])); +assert.throws(RangeError, () => calendar.fields(["second"])); +assert.throws(RangeError, () => calendar.fields(["millisecond"])); +assert.throws(RangeError, () => calendar.fields(["microsecond"])); +assert.throws(RangeError, () => calendar.fields(["nanosecond"])); +assert.throws(RangeError, () => calendar.fields(["month", "days"])); +assert.throws(RangeError, () => calendar.fields(["days"])); +assert.throws(RangeError, () => calendar.fields(["people"])); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/branding.js new file mode 100644 index 0000000000..fbfb89f314 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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.calendar.prototype.fields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const fields = Temporal.Calendar.prototype.fields; + +assert.sameValue(typeof fields, "function"); + +const args = [[]]; + +assert.throws(TypeError, () => fields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => fields.apply(null, args), "null"); +assert.throws(TypeError, () => fields.apply(true, args), "true"); +assert.throws(TypeError, () => fields.apply("", args), "empty string"); +assert.throws(TypeError, () => fields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => fields.apply(1, args), "1"); +assert.throws(TypeError, () => fields.apply({}, args), "plain object"); +assert.throws(TypeError, () => fields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => fields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/builtin.js new file mode 100644 index 0000000000..5c8387cd05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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.calendar.prototype.fields +description: > + Tests that Temporal.Calendar.prototype.fields + 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.Calendar.prototype.fields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.fields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.fields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.fields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js new file mode 100644 index 0000000000..312c745db3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: Temporal.Calendar.prototype.fields.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.Calendar.prototype.fields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js new file mode 100644 index 0000000000..88410f3d05 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/long-input.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields will throw when its input iterable yields an + invalid field. +info: | + ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iv. If nextValue is not one of "year", "month", "monthCode", or "day", then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). +features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] +---*/ +let cal = new Temporal.Calendar("iso8601") +let i = 0; +const fields = { + *[Symbol.iterator]() { + // The first three are valid values + yield "year"; + i++; + yield "month"; + i++; + yield "monthCode"; + i++; + // The fourth one is wrong and should throw after the next line. + yield "garbage"; + // The following three lines should not be reached if the implemention + // correctly check the previous line. + i++; + yield "day"; + i++; + } +} +assert.throws(RangeError, () => cal.fields(fields), "Garbage content"); +// stop after the third one. +assert.sameValue(i, 3); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/name.js new file mode 100644 index 0000000000..16a1efe247 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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.calendar.prototype.fields +description: Temporal.Calendar.prototype.fields.name is "fields". +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.Calendar.prototype.fields, "name", { + value: "fields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.js new file mode 100644 index 0000000000..c7627ff747 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/non-string-element-throws.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.calendar.prototype.fields +description: TypeError thrown if the input iterable yields a non-String value +info: | + sec-temporal.calendar.prototype.fields step 5: + 5. For each element _fieldName_ of _fieldNames_, do + a. If Type(_fieldName_) is not String, throw a *TypeError* exception. +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +[true, 3, 3n, {}, () => {}, Symbol(), undefined, null].forEach((element) => { + assert.throws(TypeError, () => calendar.fields([element]), "bad input to calendar.fields()"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/not-a-constructor.js new file mode 100644 index 0000000000..da8317c185 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields 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.Calendar.prototype.fields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.fields), false, + "isConstructor(Temporal.Calendar.prototype.fields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/prop-desc.js new file mode 100644 index 0000000000..4461f5bd3c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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.calendar.prototype.fields +description: The "fields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.fields, + "function", + "`typeof Calendar.prototype.fields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "fields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js new file mode 100644 index 0000000000..58bb67dc6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/repeated-throw.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields will throw if its input iterable yields + the same value twice. +info: | + ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iii. If fieldNames contains nextValue, then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). +features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] +---*/ +let cal = new Temporal.Calendar("iso8601") +let i = 0; +const fields = { + *[Symbol.iterator]() { + yield "month"; + i++; + yield "year"; + i++; + yield "year"; + i++; + } +} +assert.throws( + RangeError, () => cal.fields(fields), "repeated valid value should throw"); +assert.sameValue(i, 2, "Should stop at 2"); + +// Test all valid values will throw when repeated +[ "day", "monthCode", "month", "year" ].forEach((f) => { + i = 0; + const fields2 = { + *[Symbol.iterator]() { + yield f; + i++; + yield f; + i++; + } + } + assert.throws( + RangeError, () => cal.fields(fields2), "repeated valid value should throw"); + assert.sameValue(i, 1, "Should stop at 1"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js new file mode 100644 index 0000000000..88a1721cfd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/reverse.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.fields +description: > + Temporal.Calendar.prototype.fields will return the iterable in array if all + input are valid regardless of it's order. +info: | + ## 12.4.21 Temporal.Calendar.prototype.fields ( fields ) + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 4. Let iteratorRecord be ? Getiterator(fields, sync). + 5. Let fieldNames be a new empty List. + 6. Let next be true. + 7. Repeat, while next is not false, + a. Set next to ? IteratorStep(iteratorRecord). + b. If next is not false, then + i. Let nextValue be ? IteratorValue(next). + iv. If nextValue is not one of "year", "month", "monthCode", or "day", then + 1. Let completion be ThrowCompletion(a newly created RangeError object). + 2. Return ? IteratorClose(iteratorRecord, completion). +features: [Symbol, Symbol.iterator, Temporal, computed-property-names, generators] +includes: [compareArray.js] +---*/ +let cal = new Temporal.Calendar("iso8601") +const fields = { + *[Symbol.iterator]() { + yield "day"; + yield "monthCode"; + yield "month"; + yield "year"; + } +} +assert.compareArray(cal.fields(fields), Array.from(fields), + 'valid fields should be supported even if they are in reversed order of the spec'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/fields/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/Calendar/prototype/id/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/branding.js new file mode 100644 index 0000000000..447fe2b6c1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/branding.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.calendar.prototype.id +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id"); +const id = descriptor.get; + +assert.sameValue(typeof id, "function"); + +assert.throws(TypeError, () => id.call(undefined), "undefined"); +assert.throws(TypeError, () => id.call(null), "null"); +assert.throws(TypeError, () => id.call(true), "true"); +assert.throws(TypeError, () => id.call(""), "empty string"); +assert.throws(TypeError, () => id.call(Symbol()), "symbol"); +assert.throws(TypeError, () => id.call(1), "1"); +assert.throws(TypeError, () => id.call({}), "plain object"); +assert.throws(TypeError, () => id.call(Temporal.Calendar), "Temporal.Calendar"); +assert.throws(TypeError, () => id.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/custom-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/custom-calendar.js new file mode 100644 index 0000000000..25e5499b48 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/custom-calendar.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-get-temporal.calendar.prototype.id +description: Getter does not call toString(), returns the ID from internal slot +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = []; + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.observeProperty(actual, calendar, Symbol.toPrimitive, undefined); +TemporalHelpers.observeProperty(actual, calendar, "toString", function () { + actual.push("call calendar.toString"); + return "calendar ID"; +}); + +const result = calendar.id; +assert.compareArray(actual, expected); +assert.sameValue(result, "iso8601"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/prop-desc.js new file mode 100644 index 0000000000..13d41bea22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.calendar.prototype.id +description: The "id" property of Temporal.Calendar.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "id"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/id/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..8fa53a0782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.inLeapYear(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..e265505050 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.inLeapYear(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/Calendar/prototype/inLeapYear/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..767c8ba1b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.inLeapYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..30586d5b8e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.inLeapYear(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-leap-second.js new file mode 100644 index 0000000000..294783583a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.inLeapYear(arg); +assert.sameValue( + result1, + true, + "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.inLeapYear(arg); +assert.sameValue( + result2, + true, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-number.js new file mode 100644 index 0000000000..0ee5fc83da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.inLeapYear(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/Calendar/prototype/inLeapYear/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..5b4bf6c04f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.inLeapYear(arg); +assert.sameValue(result, true, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..d48face463 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.inLeapYear(arg); +assert.sameValue( + result, + true, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..32faae6439 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.inLeapYear(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..5d3a595827 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.inLeapYear(arg); +assert.sameValue(result, true, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..fa0d34bb03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + +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.inLeapYear(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.inLeapYear(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/Calendar/prototype/inLeapYear/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..0835539959 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..c4b97957a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.inLeapYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..bf2019e648 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.inLeapYear(arg); + + assert.sameValue( + result, + true, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..d7a4e32644 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..4d68cef862 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.inLeapYear(arg); + + assert.sameValue( + result, + true, + `"${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.inLeapYear(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js new file mode 100644 index 0000000000..51f36ee0cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..bb3468f3de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..ae1f291355 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-separators.js new file mode 100644 index 0000000000..be8ab2a244 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.inLeapYear(arg); + + assert.sameValue( + result, + true, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..0c410681b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.inleapyear +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.inLeapYear(arg); + + assert.sameValue( + result, + true, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..6e73f60c4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.inLeapYear(arg); + + assert.sameValue( + result, + true, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..6a1b8e81ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(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/Calendar/prototype/inLeapYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js new file mode 100644 index 0000000000..386d77fc36 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: An ISO 8601 date string should be converted as input +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! IsISOLeapYear(temporalDateLike.[[ISOYear]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.inLeapYear("2019-03-18"), false); +assert.sameValue(cal.inLeapYear("2020-03-18"), true); + +assert.sameValue(cal.inLeapYear("+002023-03-18"), false); +assert.sameValue(cal.inLeapYear("+002024-03-18"), true); + +assert.sameValue(cal.inLeapYear("2019-03-18T13:00:00+00:00[UTC]"), false); +assert.sameValue(cal.inLeapYear("2020-12-31T23:59:59+00:00[UTC]"), true); + +assert.sameValue(cal.inLeapYear("+002023-03-18T13:00:00+00:00[UTC]"), false); +assert.sameValue(cal.inLeapYear("+002024-03-18T13:00:00+00:00[UTC]"), true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-wrong-type.js new file mode 100644 index 0000000000..62c7f9da78 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + +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.inLeapYear(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.inLeapYear(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/Calendar/prototype/inLeapYear/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..0eaaa5648a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.inLeapYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..deb0f55d75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +instance.inLeapYear(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..855ce0b0a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..2133bdff72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.inLeapYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..073dfc3f0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..8156a9a9d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.inLeapYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js new file mode 100644 index 0000000000..0629f27bb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Basic tests for inLeapYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +let res = false; + +assert.sameValue(iso.inLeapYear(new Temporal.PlainDate(1994, 11, 5)), res, "PlainDate"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainDateTime(1994, 11, 5, 8, 15, 30)), res, "PlainDateTime"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainYearMonth(1994, 11)), res, "PlainYearMonth"); +assert.sameValue(iso.inLeapYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.inLeapYear("1994-11-05"), res, "string"); + +res = true; +assert.sameValue(iso.inLeapYear(new Temporal.PlainDate(1996, 7, 15)), res, "PlainDate in leap year"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainDateTime(1996, 7, 15, 5, 30, 13)), res, "PlainDateTime in leap year"); +assert.sameValue(iso.inLeapYear(new Temporal.PlainYearMonth(1996, 7)), res, "PlainYearMonth in leap year"); +assert.sameValue(iso.inLeapYear({ year: 1996, month: 7, day: 15 }), res, "property bag in leap year"); +assert.sameValue(iso.inLeapYear("1996-07-15"), res, "string in leap year"); + +assert.throws(TypeError, () => iso.inLeapYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js new file mode 100644 index 0000000000..a093d181e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const inLeapYear = Temporal.Calendar.prototype.inLeapYear; + +assert.sameValue(typeof inLeapYear, "function"); + +const args = [new Temporal.PlainDate(2021, 3, 4)]; + +assert.throws(TypeError, () => inLeapYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => inLeapYear.apply(null, args), "null"); +assert.throws(TypeError, () => inLeapYear.apply(true, args), "true"); +assert.throws(TypeError, () => inLeapYear.apply("", args), "empty string"); +assert.throws(TypeError, () => inLeapYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => inLeapYear.apply(1, args), "1"); +assert.throws(TypeError, () => inLeapYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => inLeapYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => inLeapYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/builtin.js new file mode 100644 index 0000000000..7af66d6a7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: > + Tests that Temporal.Calendar.prototype.inLeapYear + 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.Calendar.prototype.inLeapYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.inLeapYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.inLeapYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.inLeapYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..d5296d2717 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +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(); +calendar.inLeapYear({ 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/Calendar/prototype/inLeapYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js new file mode 100644 index 0000000000..d04651f126 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.inleapyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.inLeapYear({ year: 2000, month: 5, 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/Calendar/prototype/inLeapYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-temporal-object.js new file mode 100644 index 0000000000..af40ed70f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.inleapyear step 4: + 4. Let _year_ be ? ISOYear(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.inLeapYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..3800fd60d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.inLeapYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.inLeapYear({ ...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/Calendar/prototype/inLeapYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/length.js new file mode 100644 index 0000000000..c14994d608 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: Temporal.Calendar.prototype.inLeapYear.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.Calendar.prototype.inLeapYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/name.js new file mode 100644 index 0000000000..0243320bd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: Temporal.Calendar.prototype.inLeapYear.name is "inLeapYear". +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.Calendar.prototype.inLeapYear, "name", { + value: "inLeapYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/not-a-constructor.js new file mode 100644 index 0000000000..5e1ce16eef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: > + Temporal.Calendar.prototype.inLeapYear 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.Calendar.prototype.inLeapYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.inLeapYear), false, + "isConstructor(Temporal.Calendar.prototype.inLeapYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/prop-desc.js new file mode 100644 index 0000000000..43017e7fb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +description: The "inLeapYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.inLeapYear, + "function", + "`typeof Calendar.prototype.inLeapYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "inLeapYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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/Calendar/prototype/inLeapYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/year-zero.js new file mode 100644 index 0000000000..26f32ed16a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/inLeapYear/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.calendar.prototype.inleapyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js new file mode 100644 index 0000000000..a5d437c195 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-empty-object.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Either argument being an empty object should result in a copy of the other object +includes: [compareArray.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +let calls = 0; +const yearObserver = { + get year() { + calls++; + return 2021; + } +}; + +const result1 = calendar.mergeFields(yearObserver, {}); +assert.sameValue(calls, 1, "property copied"); +assert.compareArray(Object.keys(result1), ["year"]); +assert.sameValue(result1.year, 2021); +assert.sameValue(calls, 1, "result has a data property"); + +calls = 0; +const result2 = calendar.mergeFields({}, yearObserver); +assert.sameValue(calls, 1, "property copied"); +assert.compareArray(Object.keys(result2), ["year"]); +assert.sameValue(result2.year, 2021); +assert.sameValue(calls, 1, "result has a data property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js new file mode 100644 index 0000000000..3355b631d9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/arguments-not-object.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Non-object arguments are converted with ToObject and merge their [[OwnPropertyKeys]] onto a new object +includes: [compareArray.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +assert.throws(TypeError, () => calendar.mergeFields(undefined, {})); +assert.throws(TypeError, () => calendar.mergeFields({}, undefined)); + +assert.throws(TypeError, () => calendar.mergeFields(null, {})); +assert.throws(TypeError, () => calendar.mergeFields({}, null)); + +const boolResult = calendar.mergeFields(true, false); +assert.compareArray(Object.keys(boolResult), [], "Boolean objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(boolResult), null, "null-prototype object returned"); + +const numResult = calendar.mergeFields(3, 4); +assert.compareArray(Object.keys(numResult), [], "Number objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(boolResult), null, "null-prototype object returned"); + +const strResult = calendar.mergeFields("abc", "de"); +assert.compareArray(Object.keys(strResult), ["0", "1", "2"], "String objects have integer indices as own property keys"); +assert.sameValue(strResult["0"], "d"); +assert.sameValue(strResult["1"], "e"); +assert.sameValue(strResult["2"], "c"); +assert.sameValue(Object.getPrototypeOf(boolResult), null, "null-prototype object returned"); + +const symResult = calendar.mergeFields(Symbol("foo"), Symbol("bar")); +assert.compareArray(Object.keys(symResult), [], "Symbol objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(symResult), null, "null-prototype object returned"); + +const bigintResult = calendar.mergeFields(3n, 4n); +assert.compareArray(Object.keys(bigintResult), [], "BigInt objects have no own property keys"); +assert.sameValue(Object.getPrototypeOf(bigintResult), null, "null-prototype object returned"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js new file mode 100644 index 0000000000..2a9d6abacd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + Temporal.Calendar.prototype.mergeFields will merge own data properties on its + arguments +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { c: 3, d: 4 }), + { a: 1, b: 2, c: 3, d: 4 }, + "properties are merged" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4 }, + "property in additionalFields should overwrite one in fields" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/branding.js new file mode 100644 index 0000000000..9fc1451238 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/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.calendar.prototype.mergefields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const mergeFields = Temporal.Calendar.prototype.mergeFields; + +assert.sameValue(typeof mergeFields, "function"); + +const args = [{}, {}]; + +assert.throws(TypeError, () => mergeFields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => mergeFields.apply(null, args), "null"); +assert.throws(TypeError, () => mergeFields.apply(true, args), "true"); +assert.throws(TypeError, () => mergeFields.apply("", args), "empty string"); +assert.throws(TypeError, () => mergeFields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => mergeFields.apply(1, args), "1"); +assert.throws(TypeError, () => mergeFields.apply({}, args), "plain object"); +assert.throws(TypeError, () => mergeFields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => mergeFields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/builtin.js new file mode 100644 index 0000000000..6f7cee257c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/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.calendar.prototype.mergefields +description: > + Tests that Temporal.Calendar.prototype.mergeFields + 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.Calendar.prototype.mergeFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.mergeFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.mergeFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.mergeFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js new file mode 100644 index 0000000000..d223e63931 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js @@ -0,0 +1,102 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: > + The default mergeFields algorithm from the ISO 8601 calendar should correctly + merge the month and monthCode properties +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, month: 7 }, + "month is copied from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M08" }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, monthCode: "M08" }, + "monthCode is copied from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4 }), + { a: 1, b: 3, c: 4, month: 7, monthCode: "M08" }, + "both month and monthCode are copied from fields, no validation is performed" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month is copied from additionalFields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06" }, + "monthCode is copied from additionalFields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2 }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields, no validation is performed" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month from additionalFields overrides month from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, monthCode: "M05" }), + { a: 1, b: 3, c: 4, monthCode: "M05" }, + "monthCode from additionalFields overrides monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, month: 6 }), + { a: 1, b: 3, c: 4, month: 6 }, + "month's presence on additionalFields blocks monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06"}, + "monthCode's presence on additionalFields blocks month from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" },{ b: 3, c: 4, month: 5 }), + { a: 1, b: 3, c: 4, month: 5 }, + "month's presence on additionalFields blocks both month and monthCode from fields" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4, monthCode: "M06" }), + { a: 1, b: 3, c: 4, monthCode: "M06" }, + "monthCode's presence on additionalFields blocks both month and monthCode from fields" +); + +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7 }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has month" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, monthCode: "M07" }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has monthCode" +); +assert.deepEqual( + cal.mergeFields({ a: 1, b: 2, month: 7, monthCode: "M08" }, { b: 3, c: 4, month: 5, monthCode: "M06" }), + { a: 1, b: 3, c: 4, month: 5, monthCode: "M06" }, + "both month and monthCode are copied from additionalFields even when fields has both month and monthCode" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js new file mode 100644 index 0000000000..fa2778be25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Temporal.Calendar.prototype.mergeFields.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.mergeFields, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/name.js new file mode 100644 index 0000000000..23c4ea861c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/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.calendar.prototype.mergefields +description: Temporal.Calendar.prototype.mergeFields.name is "mergeFields". +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.Calendar.prototype.mergeFields, "name", { + value: "mergeFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js new file mode 100644 index 0000000000..b78f828d4f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Both string and symbol keys from the arguments are merged +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. Set fields to ? ToObject(fields). + 5. Set additionalFields to ? ToObject(additionalFields). + 6. Return ? DefaultMergeFields(fields, additionalFields). +features: [Temporal] +---*/ + +function assertEntriesEqual(actual, expectedEntries, message) { + const names = Object.getOwnPropertyNames(actual); + const symbols = Object.getOwnPropertySymbols(actual); + const actualKeys = names.concat(symbols); + assert.sameValue( + actualKeys.length, + expectedEntries.length, + `${message}: expected object to have ${expectedEntries.length} properties, not ${actualKeys.length}:` + ); + for (var index = 0; index < actualKeys.length; index++) { + const actualKey = actualKeys[index]; + const expectedKey = expectedEntries[index][0]; + const expectedValue = expectedEntries[index][1]; + assert.sameValue(actualKey, expectedKey, `${message}: key ${index}:`); + assert.sameValue(actual[actualKey], expectedValue, `${message}: value ${index}:`); + } +} + +const cal = new Temporal.Calendar("iso8601"); + +assertEntriesEqual( + cal.mergeFields({ 1: 2 }, { 3: 4 }), + [["1", 2], ["3", 4]], + "number keys are actually string keys and are merged as such" +); +assertEntriesEqual( + cal.mergeFields({ 1n: 2 }, { 2n: 4 }), + [["1", 2], ["2", 4]], + "bigint keys are actually string keys and are merged as such" +); + +const foo = Symbol("foo"); +const bar = Symbol("bar"); +assertEntriesEqual( + cal.mergeFields({ [foo]: 1 }, { [bar]: 2 }), + [[foo, 1], [bar, 2]], + "symbol keys are also merged" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/not-a-constructor.js new file mode 100644 index 0000000000..c53ddcbf32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/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.calendar.prototype.mergefields +description: > + Temporal.Calendar.prototype.mergeFields 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.Calendar.prototype.mergeFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.mergeFields), false, + "isConstructor(Temporal.Calendar.prototype.mergeFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/order-of-operations.js new file mode 100644 index 0000000000..38cd82d5ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/order-of-operations.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.mergefields +description: Properties on objects passed to mergeFields() are accessed in the correct order +features: [Temporal] +includes: [compareArray.js, temporalHelpers.js] +---*/ + +const expected = [ + // CopyDataProperties on fields + "ownKeys fields", + "getOwnPropertyDescriptor fields.year", + "get fields.year", + "getOwnPropertyDescriptor fields.month", + "get fields.month", + "getOwnPropertyDescriptor fields.day", + "get fields.day", + "getOwnPropertyDescriptor fields.extra", + "get fields.extra", + // CopyDataProperties on additionalFields + "ownKeys additionalFields", + "getOwnPropertyDescriptor additionalFields[3]", + "get additionalFields[3]", + "getOwnPropertyDescriptor additionalFields.monthCode", + "get additionalFields.monthCode", + "getOwnPropertyDescriptor additionalFields[Symbol('extra')]", + "get additionalFields[Symbol('extra')]", +]; +const actual = []; + +const fields = TemporalHelpers.propertyBagObserver(actual, { + year: 2022, + month: 10, + day: 17, + extra: "extra property", +}, "fields"); +const additionalFields = TemporalHelpers.propertyBagObserver(actual, { + [Symbol("extra")]: "extra symbol property", + monthCode: "M10", + 3: "extra array index property", +}, "additionalFields"); + +const instance = new Temporal.Calendar("iso8601"); +instance.mergeFields(fields, additionalFields); +assert.compareArray(actual, expected, "order of observable operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/prop-desc.js new file mode 100644 index 0000000000..4c4f0e8d56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/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.calendar.prototype.mergefields +description: The "mergeFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.mergeFields, + "function", + "`typeof Calendar.prototype.mergeFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "mergeFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js new file mode 100644 index 0000000000..346758ebd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/mergeFields/shell.js @@ -0,0 +1,353 @@ +// GENERATED, DO NOT EDIT +// file: deepEqual.js +// Copyright 2019 Ron Buckton. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Compare two values structurally +defines: [assert.deepEqual] +---*/ + +assert.deepEqual = function(actual, expected, message) { + var format = assert.deepEqual.format; + assert( + assert.deepEqual._compare(actual, expected), + `Expected ${format(actual)} to be structurally equal to ${format(expected)}. ${(message || '')}` + ); +}; + +assert.deepEqual.format = function(value, seen) { + switch (typeof value) { + case 'string': + return typeof JSON !== "undefined" ? JSON.stringify(value) : `"${value}"`; + case 'number': + case 'boolean': + case 'symbol': + case 'bigint': + return value.toString(); + case 'undefined': + return 'undefined'; + case 'function': + return `[Function${value.name ? `: ${value.name}` : ''}]`; + case 'object': + if (value === null) return 'null'; + if (value instanceof Date) return `Date "${value.toISOString()}"`; + if (value instanceof RegExp) return value.toString(); + if (!seen) { + seen = { + counter: 0, + map: new Map() + }; + } + + let usage = seen.map.get(value); + if (usage) { + usage.used = true; + return `[Ref: #${usage.id}]`; + } + + usage = { id: ++seen.counter, used: false }; + seen.map.set(value, usage); + + if (typeof Set !== "undefined" && value instanceof Set) { + return `Set {${Array.from(value).map(value => assert.deepEqual.format(value, seen)).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (typeof Map !== "undefined" && value instanceof Map) { + return `Map {${Array.from(value).map(pair => `${assert.deepEqual.format(pair[0], seen)} => ${assert.deepEqual.format(pair[1], seen)}}`).join(', ')}}${usage.used ? ` as #${usage.id}` : ''}`; + } + if (Array.isArray ? Array.isArray(value) : value instanceof Array) { + return `[${value.map(value => assert.deepEqual.format(value, seen)).join(', ')}]${usage.used ? ` as #${usage.id}` : ''}`; + } + let tag = Symbol.toStringTag in value ? value[Symbol.toStringTag] : 'Object'; + if (tag === 'Object' && Object.getPrototypeOf(value) === null) { + tag = '[Object: null prototype]'; + } + return `${tag ? `${tag} ` : ''}{ ${Object.keys(value).map(key => `${key.toString()}: ${assert.deepEqual.format(value[key], seen)}`).join(', ')} }${usage.used ? ` as #${usage.id}` : ''}`; + default: + return typeof value; + } +}; + +assert.deepEqual._compare = (function () { + var EQUAL = 1; + var NOT_EQUAL = -1; + var UNKNOWN = 0; + + function deepEqual(a, b) { + return compareEquality(a, b) === EQUAL; + } + + function compareEquality(a, b, cache) { + return compareIf(a, b, isOptional, compareOptionality) + || compareIf(a, b, isPrimitiveEquatable, comparePrimitiveEquality) + || compareIf(a, b, isObjectEquatable, compareObjectEquality, cache) + || NOT_EQUAL; + } + + function compareIf(a, b, test, compare, cache) { + return !test(a) + ? !test(b) ? UNKNOWN : NOT_EQUAL + : !test(b) ? NOT_EQUAL : cacheComparison(a, b, compare, cache); + } + + function tryCompareStrictEquality(a, b) { + return a === b ? EQUAL : UNKNOWN; + } + + function tryCompareTypeOfEquality(a, b) { + return typeof a !== typeof b ? NOT_EQUAL : UNKNOWN; + } + + function tryCompareToStringTagEquality(a, b) { + var aTag = Symbol.toStringTag in a ? a[Symbol.toStringTag] : undefined; + var bTag = Symbol.toStringTag in b ? b[Symbol.toStringTag] : undefined; + return aTag !== bTag ? NOT_EQUAL : UNKNOWN; + } + + function isOptional(value) { + return value === undefined + || value === null; + } + + function compareOptionality(a, b) { + return tryCompareStrictEquality(a, b) + || NOT_EQUAL; + } + + function isPrimitiveEquatable(value) { + switch (typeof value) { + case 'string': + case 'number': + case 'bigint': + case 'boolean': + case 'symbol': + return true; + default: + return isBoxed(value); + } + } + + function comparePrimitiveEquality(a, b) { + if (isBoxed(a)) a = a.valueOf(); + if (isBoxed(b)) b = b.valueOf(); + return tryCompareStrictEquality(a, b) + || tryCompareTypeOfEquality(a, b) + || compareIf(a, b, isNaNEquatable, compareNaNEquality) + || NOT_EQUAL; + } + + function isNaNEquatable(value) { + return typeof value === 'number'; + } + + function compareNaNEquality(a, b) { + return isNaN(a) && isNaN(b) ? EQUAL : NOT_EQUAL; + } + + function isObjectEquatable(value) { + return typeof value === 'object'; + } + + function compareObjectEquality(a, b, cache) { + if (!cache) cache = new Map(); + return getCache(cache, a, b) + || setCache(cache, a, b, EQUAL) // consider equal for now + || cacheComparison(a, b, tryCompareStrictEquality, cache) + || cacheComparison(a, b, tryCompareToStringTagEquality, cache) + || compareIf(a, b, isValueOfEquatable, compareValueOfEquality) + || compareIf(a, b, isToStringEquatable, compareToStringEquality) + || compareIf(a, b, isArrayLikeEquatable, compareArrayLikeEquality, cache) + || compareIf(a, b, isStructurallyEquatable, compareStructuralEquality, cache) + || compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || cacheComparison(a, b, fail, cache); + } + + function isBoxed(value) { + return value instanceof String + || value instanceof Number + || value instanceof Boolean + || typeof Symbol === 'function' && value instanceof Symbol + || typeof BigInt === 'function' && value instanceof BigInt; + } + + function isValueOfEquatable(value) { + return value instanceof Date; + } + + function compareValueOfEquality(a, b) { + return compareIf(a.valueOf(), b.valueOf(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isToStringEquatable(value) { + return value instanceof RegExp; + } + + function compareToStringEquality(a, b) { + return compareIf(a.toString(), b.toString(), isPrimitiveEquatable, comparePrimitiveEquality) + || NOT_EQUAL; + } + + function isArrayLikeEquatable(value) { + return (Array.isArray ? Array.isArray(value) : value instanceof Array) + || (typeof Uint8Array === 'function' && value instanceof Uint8Array) + || (typeof Uint8ClampedArray === 'function' && value instanceof Uint8ClampedArray) + || (typeof Uint16Array === 'function' && value instanceof Uint16Array) + || (typeof Uint32Array === 'function' && value instanceof Uint32Array) + || (typeof Int8Array === 'function' && value instanceof Int8Array) + || (typeof Int16Array === 'function' && value instanceof Int16Array) + || (typeof Int32Array === 'function' && value instanceof Int32Array) + || (typeof Float32Array === 'function' && value instanceof Float32Array) + || (typeof Float64Array === 'function' && value instanceof Float64Array) + || (typeof BigUint64Array === 'function' && value instanceof BigUint64Array) + || (typeof BigInt64Array === 'function' && value instanceof BigInt64Array); + } + + function compareArrayLikeEquality(a, b, cache) { + if (a.length !== b.length) return NOT_EQUAL; + for (var i = 0; i < a.length; i++) { + if (compareEquality(a[i], b[i], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + return EQUAL; + } + + function isStructurallyEquatable(value) { + return !(typeof Promise === 'function' && value instanceof Promise // only comparable by reference + || typeof WeakMap === 'function' && value instanceof WeakMap // only comparable by reference + || typeof WeakSet === 'function' && value instanceof WeakSet // only comparable by reference + || typeof Map === 'function' && value instanceof Map // comparable via @@iterator + || typeof Set === 'function' && value instanceof Set); // comparable via @@iterator + } + + function compareStructuralEquality(a, b, cache) { + var aKeys = []; + for (var key in a) aKeys.push(key); + + var bKeys = []; + for (var key in b) bKeys.push(key); + + if (aKeys.length !== bKeys.length) { + return NOT_EQUAL; + } + + aKeys.sort(); + bKeys.sort(); + + for (var i = 0; i < aKeys.length; i++) { + var aKey = aKeys[i]; + var bKey = bKeys[i]; + if (compareEquality(aKey, bKey, cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + if (compareEquality(a[aKey], b[bKey], cache) === NOT_EQUAL) { + return NOT_EQUAL; + } + } + + return compareIf(a, b, isIterableEquatable, compareIterableEquality, cache) + || EQUAL; + } + + function isIterableEquatable(value) { + return typeof Symbol === 'function' + && typeof value[Symbol.iterator] === 'function'; + } + + function compareIteratorEquality(a, b, cache) { + if (typeof Map === 'function' && a instanceof Map && b instanceof Map || + typeof Set === 'function' && a instanceof Set && b instanceof Set) { + if (a.size !== b.size) return NOT_EQUAL; // exit early if we detect a difference in size + } + + var ar, br; + while (true) { + ar = a.next(); + br = b.next(); + if (ar.done) { + if (br.done) return EQUAL; + if (b.return) b.return(); + return NOT_EQUAL; + } + if (br.done) { + if (a.return) a.return(); + return NOT_EQUAL; + } + if (compareEquality(ar.value, br.value, cache) === NOT_EQUAL) { + if (a.return) a.return(); + if (b.return) b.return(); + return NOT_EQUAL; + } + } + } + + function compareIterableEquality(a, b, cache) { + return compareIteratorEquality(a[Symbol.iterator](), b[Symbol.iterator](), cache); + } + + function cacheComparison(a, b, compare, cache) { + var result = compare(a, b, cache); + if (cache && (result === EQUAL || result === NOT_EQUAL)) { + setCache(cache, a, b, /** @type {EQUAL | NOT_EQUAL} */(result)); + } + return result; + } + + function fail() { + return NOT_EQUAL; + } + + function setCache(cache, left, right, result) { + var otherCache; + + otherCache = cache.get(left); + if (!otherCache) cache.set(left, otherCache = new Map()); + otherCache.set(right, result); + + otherCache = cache.get(right); + if (!otherCache) cache.set(right, otherCache = new Map()); + otherCache.set(left, result); + } + + function getCache(cache, left, right) { + var otherCache; + var result; + + otherCache = cache.get(left); + result = otherCache && otherCache.get(right); + if (result) return result; + + otherCache = cache.get(right); + result = otherCache && otherCache.get(left); + if (result) return result; + + return UNKNOWN; + } + + return deepEqual; +})(); + +// 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/Calendar/prototype/month/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..f3ad260dbc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.month(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..0c45a60cc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.month(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/Calendar/prototype/month/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..b42eb7eedb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.month(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..6c9458de2b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.month(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-leap-second.js new file mode 100644 index 0000000000..faaa158e03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.month(arg); +assert.sameValue( + result1, + 12, + "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.month(arg); +assert.sameValue( + result2, + 12, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-number.js new file mode 100644 index 0000000000..e9ad09de4b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.month(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/Calendar/prototype/month/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..0bd26a63b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.month(arg); +assert.sameValue(result, 11, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..7af34e9cb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.month(arg); +assert.sameValue( + result, + 11, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..dd8ce27a1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.month(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..b7d15b225b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.month(arg); +assert.sameValue(result, 11, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..173852f0b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + +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.month(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.month(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/Calendar/prototype/month/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..81bd484995 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..f81d9391a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.month(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..ac8502eab0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.month(arg); + + assert.sameValue( + result, + 5, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..fbd525323b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..460fbfdc95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.month(arg); + + assert.sameValue( + result, + 5, + `"${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.month(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js new file mode 100644 index 0000000000..8ef222a838 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.month(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..2318d545b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..abfed3580c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-separators.js new file mode 100644 index 0000000000..6166133d3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.month(arg); + + assert.sameValue( + result, + 5, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..d5d9b46388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.month +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.month(arg); + + assert.sameValue( + result, + 5, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..b0eb8ca2e2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.month(arg); + + assert.sameValue( + result, + 5, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..6a85186669 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(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/Calendar/prototype/month/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-wrong-type.js new file mode 100644 index 0000000000..2edf45bb54 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + +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.month(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.month(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/Calendar/prototype/month/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..efa7901fbd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.month(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..083973936e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +instance.month(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..a17f4788fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..ee000ce22d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.month(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..a8c8823177 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..7ed7627662 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.month(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js new file mode 100644 index 0000000000..737bcc99bb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/basic.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Basic tests for month(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 11; +assert.sameValue(iso.month(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.month(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.month(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.month({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.month("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.month({ year: 2000 }), "property bag with missing properties"); +assert.throws(TypeError, () => iso.month(Temporal.PlainMonthDay.from("11-05")), "PlainMonthDay"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/branding.js new file mode 100644 index 0000000000..505485af9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const month = Temporal.Calendar.prototype.month; + +assert.sameValue(typeof month, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => month.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => month.apply(null, args), "null"); +assert.throws(TypeError, () => month.apply(true, args), "true"); +assert.throws(TypeError, () => month.apply("", args), "empty string"); +assert.throws(TypeError, () => month.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => month.apply(1, args), "1"); +assert.throws(TypeError, () => month.apply({}, args), "plain object"); +assert.throws(TypeError, () => month.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => month.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/builtin.js new file mode 100644 index 0000000000..398501e3ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: > + Tests that Temporal.Calendar.prototype.month + 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.Calendar.prototype.month), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.month), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.month), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.month.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..b6ad45d5f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +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(); +calendar.month({ 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/Calendar/prototype/month/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js new file mode 100644 index 0000000000..d43a81b98d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.month step 4: + 4. Return ? ISOMonth(_dateOrDateTime_). + sec-temporal-isomonth step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.month({ year: 2000, month: 5, 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/Calendar/prototype/month/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js new file mode 100644 index 0000000000..47f9b6875e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.month step 4: + 4. Return ? ISOMonth(_dateOrDateTime_). + sec-temporal-isomonth step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.month({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js new file mode 100644 index 0000000000..a78719d1fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date-time.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month will take PlainDateTime and return + the value of the month. +info: | + 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] + internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 6. Return ! ISOMonth(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dateTime = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13) +assert.sameValue(cal.month(dateTime), 8, 'cal.month(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 8'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js new file mode 100644 index 0000000000..c5a2aa42f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/date.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month will take PlainDate and return + the value of the month. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(temporalDateLike) is Object and temporalDateLike has an + [[InitializedTemporalMonthDay]] internal slot, then + a. Throw a TypeError exception. + 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] + internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 6. Return ! ISOMonth(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let date = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.month(date), 7, 'cal.month(new Temporal.PlainDate(2021, 7, 15)) must return 7'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..c54d8d66c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.month({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.month({ ...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/Calendar/prototype/month/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/length.js new file mode 100644 index 0000000000..29b41d9b57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: Temporal.Calendar.prototype.month.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.Calendar.prototype.month, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js new file mode 100644 index 0000000000..2d03d4aa6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/month-day-throw-type-error.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month throws TypeError if temporalDateLike + is a PlainMonthDay object. + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is Object and temporalDateLike has an + [[InitializedTemporalMonthDay]] internal slot, then + a. Throw a TypeError exception. +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let monthDay = new Temporal.PlainMonthDay(12, 25); +assert.throws(TypeError, () => cal.month(monthDay), + 'cal.month(monthDay) throws a TypeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/name.js new file mode 100644 index 0000000000..1a154f7878 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: Temporal.Calendar.prototype.month.name is "month". +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.Calendar.prototype.month, "name", { + value: "month", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/not-a-constructor.js new file mode 100644 index 0000000000..daab6ff41d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month 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.Calendar.prototype.month(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.month), false, + "isConstructor(Temporal.Calendar.prototype.month)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/prop-desc.js new file mode 100644 index 0000000000..3359b2fdaf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +description: The "month" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.month, + "function", + "`typeof Calendar.prototype.month` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "month", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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/Calendar/prototype/month/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js new file mode 100644 index 0000000000..8b6e2f20c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/string.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month will take ISO8601 string and return + the value of the month. +info: | + 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 6. Return ! ISOMonth(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.month("2019-03-15"), 3, 'cal.month("2019-03-15") must return 3'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..9b166de02b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/throw-range-error-ToTemporalDate.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 5. If Type(temporalDateLike) is not Object or temporalDateLike + does not have an [[InitializedTemporalDate]] or + [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.month("invalid string"), + 'cal.month("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js new file mode 100644 index 0000000000..23c6dbc614 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-month.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + Temporal.Calendar.prototype.month will take PlainYearMonth and return + the value of the month. +info: | + 6. Return ! ISOMonth(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let yearMonth = new Temporal.PlainYearMonth(1999, 6); +assert.sameValue(cal.month(yearMonth), 6, 'cal.month(new Temporal.PlainYearMonth(1999, 6)) must return 6'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/year-zero.js new file mode 100644 index 0000000000..8468e9c316 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/month/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.calendar.prototype.month +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.month(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..8e5875e685 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.monthCode(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..1a62ba4e88 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.monthCode(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/Calendar/prototype/monthCode/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..d79f744214 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.monthCode(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..a2693c6070 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.monthCode(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-leap-second.js new file mode 100644 index 0000000000..7a6fd3166b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.monthCode(arg); +assert.sameValue( + result1, + "M12", + "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.monthCode(arg); +assert.sameValue( + result2, + "M12", + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-number.js new file mode 100644 index 0000000000..8d4f0a0bdf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.monthCode(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/Calendar/prototype/monthCode/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..678a9771fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthCode(arg); +assert.sameValue(result, "M11", "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..d15cc3d900 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthCode(arg); +assert.sameValue( + result, + "M11", + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..a56e94238d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.monthCode(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..272b8a6495 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthCode(arg); +assert.sameValue(result, "M11", `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..457e61182b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + +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.monthCode(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.monthCode(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/Calendar/prototype/monthCode/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..24178dfdb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..ce95efc5da --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.monthCode(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..6fdc89f24b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthCode(arg); + + assert.sameValue( + result, + "M05", + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..eb87fb6809 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..1079461479 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.monthCode(arg); + + assert.sameValue( + result, + "M05", + `"${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.monthCode(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js new file mode 100644 index 0000000000..06f1861f25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..57d58733e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..eee5dca1fe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-separators.js new file mode 100644 index 0000000000..a51b45457f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthCode(arg); + + assert.sameValue( + result, + "M05", + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..0aebca570e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.monthcode +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthCode(arg); + + assert.sameValue( + result, + "M05", + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..c129776c7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthCode(arg); + + assert.sameValue( + result, + "M05", + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..bbaf4e93a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(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/Calendar/prototype/monthCode/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-wrong-type.js new file mode 100644 index 0000000000..c48b97ca0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + +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.monthCode(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.monthCode(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/Calendar/prototype/monthCode/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..310546e282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.monthCode(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..66651d80d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +instance.monthCode(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..75cc814a12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..52d16e579f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.monthCode(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..c9a0bdf5a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..c5f71da604 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.monthCode(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js new file mode 100644 index 0000000000..6d841cf1f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/basic.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Basic tests for monthCode(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = "M11"; +assert.sameValue(iso.monthCode(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.monthCode(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.monthCode(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.monthCode(Temporal.PlainMonthDay.from("11-05")), res, "PlainMonthDay"); +assert.sameValue(iso.monthCode({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.monthCode("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.monthCode({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/branding.js new file mode 100644 index 0000000000..cd47822052 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const monthCode = Temporal.Calendar.prototype.monthCode; + +assert.sameValue(typeof monthCode, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => monthCode.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => monthCode.apply(null, args), "null"); +assert.throws(TypeError, () => monthCode.apply(true, args), "true"); +assert.throws(TypeError, () => monthCode.apply("", args), "empty string"); +assert.throws(TypeError, () => monthCode.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => monthCode.apply(1, args), "1"); +assert.throws(TypeError, () => monthCode.apply({}, args), "plain object"); +assert.throws(TypeError, () => monthCode.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => monthCode.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/builtin.js new file mode 100644 index 0000000000..7ec3413f6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: > + Tests that Temporal.Calendar.prototype.monthCode + 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.Calendar.prototype.monthCode), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthCode), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthCode), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthCode.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..cb047b7afe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +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(); +calendar.monthCode({ 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/Calendar/prototype/monthCode/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js new file mode 100644 index 0000000000..848ff29298 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.monthcode step 4: + 4. Return ? ISOMonthCode(_dateOrDateTime_). + sec-temporal-isomonthcode step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.monthCode({ year: 2000, month: 5, 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/Calendar/prototype/monthCode/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js new file mode 100644 index 0000000000..097aede616 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.monthcode step 4: + 4. Return ? ISOMonthCode(_dateOrDateTime_). + sec-temporal-isomonthcode step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.monthCode({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js new file mode 100644 index 0000000000..067d4187ad --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date-time.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.month will take PlainDateTime and return + the value of the monthCode. +info: | + 6. Return ! ISOMonthCode(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dateTime = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13) +assert.sameValue( + cal.monthCode(dateTime), + "M08", + 'cal.monthCode(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return "M08"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js new file mode 100644 index 0000000000..4493a17377 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/date.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.monthCode will take PlainDate and return + the value of the monthCode. +info: | + 5. Return ! ISOMonthCode(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let date = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.monthCode(date), "M07", 'cal.monthCode(new Temporal.PlainDate(2021, 7, 15)) must return "M07"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..838f979d19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.monthCode({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthCode({ ...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/Calendar/prototype/monthCode/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js new file mode 100644 index 0000000000..7556b38e55 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: Temporal.Calendar.prototype.monthCode.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.Calendar.prototype.monthCode, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js new file mode 100644 index 0000000000..23b0f65468 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/month-day.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.monthCode will take PlainMonthDay and return + the value of the monthCode. +info: | + 6. Return ! ISOMonthCode(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let monthDay = new Temporal.PlainMonthDay(12, 25); +assert.sameValue( + cal.monthCode(monthDay), + "M12", + 'cal.monthCode(new Temporal.PlainMonthDay(12, 25)) must return "M12"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/name.js new file mode 100644 index 0000000000..4550c2cdc3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: Temporal.Calendar.prototype.monthCode.name is "monthCode". +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.Calendar.prototype.monthCode, "name", { + value: "monthCode", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/not-a-constructor.js new file mode 100644 index 0000000000..e79c22ca20 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: > + Temporal.Calendar.prototype.monthCode 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.Calendar.prototype.monthCode(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthCode), false, + "isConstructor(Temporal.Calendar.prototype.monthCode)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/prop-desc.js new file mode 100644 index 0000000000..2e22953632 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +description: The "monthCode" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthCode, + "function", + "`typeof Calendar.prototype.monthCode` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthCode", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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/Calendar/prototype/monthCode/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js new file mode 100644 index 0000000000..1bd095b893 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/string.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.monthCode will take ISO8601 string and return + the value of the monthCode. +info: | + 5. If Type(temporalDateLike) is not Object or temporalDateLike does not have + an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal + slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 6. Return ! ISOYear(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); +assert.sameValue( + cal.monthCode("2019-03-15"), + "M03", + 'cal.monthCode("2019-03-15") must return "M03"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..80ea2299f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/throw-range-error-ToTemporalDate.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.monthCode throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike + does not have an [[InitializedTemporalDate]] or + [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.monthCode("invalid string"), + 'cal.monthCode("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js new file mode 100644 index 0000000000..c0b553658e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-month.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthCode +description: > + Temporal.Calendar.prototype.monthCode will take PlainYearMonth and return + the value of the monthCode. +info: | + 6. Return ! ISOMonthCode(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let yearMonth = new Temporal.PlainYearMonth(1999, 6); +assert.sameValue( + cal.monthCode(yearMonth), + "M06", + 'cal.monthCode(new Temporal.PlainYearMonth(1999, 6)) must return "M06"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/year-zero.js new file mode 100644 index 0000000000..9a7df06b6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthCode/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.calendar.prototype.monthcode +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthCode(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js new file mode 100644 index 0000000000..09ca1c9b00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »). + 7. Let overflow be ? ToTemporalOverflow(options). + 8. Perform ? ISOResolveMonth(fields). + 9. Let result be ? ISOMonthDayFromFields(fields, overflow). + 10. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], "iso8601", result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +const options = [ + { overflow: "constrain" }, + { overflow: "reject" }, + {}, + undefined, +]; +options.forEach((opt) => { + const optionsDesc = opt && JSON.stringify(opt); + result = cal.monthDayFromFields({ year: 2021, month: 7, day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, `month 7, day 3, with year, options = ${optionsDesc}`); + result = cal.monthDayFromFields({ year: 2021, month: 12, day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, `month 12, day 31, with year, options = ${optionsDesc}`); + result = cal.monthDayFromFields({ monthCode: "M07", day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, `monthCode M07, day 3, options = ${optionsDesc}`); + result = cal.monthDayFromFields({ monthCode: "M12", day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, `monthCode M12, day 31, options = ${optionsDesc}`); +}); + +TemporalHelpers.ISOMonths.forEach(({ month, monthCode, daysInMonth }) => { + result = cal.monthDayFromFields({ month, day: daysInMonth }); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, `month ${month}, day ${daysInMonth}`); + + result = cal.monthDayFromFields({ monthCode, day: daysInMonth }); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, `monthCode ${monthCode}, day ${daysInMonth}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/branding.js new file mode 100644 index 0000000000..3fe68f7011 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const monthDayFromFields = Temporal.Calendar.prototype.monthDayFromFields; + +assert.sameValue(typeof monthDayFromFields, "function"); + +const args = [{ monthCode: "M01", day: 1 }]; + +assert.throws(TypeError, () => monthDayFromFields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => monthDayFromFields.apply(null, args), "null"); +assert.throws(TypeError, () => monthDayFromFields.apply(true, args), "true"); +assert.throws(TypeError, () => monthDayFromFields.apply("", args), "empty string"); +assert.throws(TypeError, () => monthDayFromFields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => monthDayFromFields.apply(1, args), "1"); +assert.throws(TypeError, () => monthDayFromFields.apply({}, args), "plain object"); +assert.throws(TypeError, () => monthDayFromFields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => monthDayFromFields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/builtin.js new file mode 100644 index 0000000000..0928552344 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: > + Tests that Temporal.Calendar.prototype.monthDayFromFields + 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.Calendar.prototype.monthDayFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthDayFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthDayFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthDayFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js new file mode 100644 index 0000000000..12ca8c5475 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »). + 7. Let overflow be ? ToTemporalOverflow(options). + 8. Perform ? ISOResolveMonth(fields). + 9. Let result be ? ISOMonthDayFromFields(fields, overflow). + 10. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], "iso8601", result.[[ReferenceISOYear]]). +features: [Temporal] +---*/ + +let cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.monthDayFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.monthDayFromFields({ month: 12 }), "day is required with month"); +assert.throws(TypeError, () => cal.monthDayFromFields({ monthCode: "M12" }), "day is required with monthCode"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, month: 12 }), "day is required with year and month"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, monthCode: "M12" }), "day is required with year and monthCode"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, day: 17 }), "either month or monthCode is required"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js new file mode 100644 index 0000000000..77991bbcef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.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.calendar.prototype.monthdayfromfields +description: Throw a TypeError if the fields is not an object +features: [Symbol, Temporal] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws(TypeError, () => iso.monthDayFromFields(fields, {})); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..b07372e0a7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/infinity-throws-rangeerror.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. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.monthdayfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthDayFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/length.js new file mode 100644 index 0000000000..ab0bc26c02 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields.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.Calendar.prototype.monthDayFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/missing-properties.js new file mode 100644 index 0000000000..85331cb3d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/missing-properties.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.calendar.prototype.monthdayfromfields +description: Errors due to missing properties on fields object are thrown in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const missingDay = { + get year() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, + get month() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, + get monthCode() { + TemporalHelpers.assertUnreachable("day should be checked first"); + }, +}; +assert.throws(TypeError, () => instance.monthDayFromFields(missingDay), "day should be checked before year and month"); + +let got = []; +const fieldsSpy = TemporalHelpers.propertyBagObserver(got, { day: 1 }); +assert.throws(TypeError, () => instance.monthDayFromFields(fieldsSpy), "incomplete fields should be rejected (but after reading all non-required fields)"); +assert.compareArray(got, [ + "get day", + "get day.valueOf", + "call day.valueOf", + "get month", + "get monthCode", + "get year", +], "fields should be read in alphabetical order"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js new file mode 100644 index 0000000000..04424ff5c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.monthDayFromFields({ monthCode, day: 17 }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.monthDayFromFields({ year: 2021, month: 12, monthCode: "M11", day: 17 }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.monthDayFromFields({ monthCode, day: 17 }), + `monthCode '${monthCode}' is not valid for ISO 8601 calendar`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/name.js new file mode 100644 index 0000000000..116caa43cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields.name is "monthDayFromFields". +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.Calendar.prototype.monthDayFromFields, "name", { + value: "monthDayFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/not-a-constructor.js new file mode 100644 index 0000000000..a9950ff3e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: > + Temporal.Calendar.prototype.monthDayFromFields 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.Calendar.prototype.monthDayFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthDayFromFields), false, + "isConstructor(Temporal.Calendar.prototype.monthDayFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/one-of-era-erayear-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/one-of-era-erayear-undefined.js new file mode 100644 index 0000000000..bc8f5b6f27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/one-of-era-erayear-undefined.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.calendar.prototype.monthDayFromFields +description: Does not throw a RangeError if only one of era/eraYear fields is present +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const base = { year: 2000, month: 5, day: 2, era: 'ce' }; +const instance = new Temporal.Calendar('iso8601'); +TemporalHelpers.assertPlainMonthDay(instance.monthDayFromFields({ ...base }), 'M05', 2); + +const base2 = { year: 2000, month: 5, day: 2, eraYear: 1 }; +TemporalHelpers.assertPlainMonthDay(instance.monthDayFromFields({ ...base }), 'M05', 2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-object.js new file mode 100644 index 0000000000..277bec6757 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const result1 = instance.monthDayFromFields({ monthCode: "M12", day: 15 }, {}); +TemporalHelpers.assertPlainMonthDay( + result1, "M12", 15, + "options may be an empty plain object" +); + +const result2 = instance.monthDayFromFields({ monthCode: "M12", day: 15 }, () => {}); +TemporalHelpers.assertPlainMonthDay( + result2, "M12", 15, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.js new file mode 100644 index 0000000000..4ffb442486 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +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.Calendar("iso8601"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.monthDayFromFields({ monthCode: "M12", day: 15 }, value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/order-of-operations.js new file mode 100644 index 0000000000..e7e7458af8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/order-of-operations.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.calendar.prototype.monthdayfromfields +description: Properties on objects passed to monthDayFromFields() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get fields.day", + "get fields.day.valueOf", + "call fields.day.valueOf", + "get fields.month", + "get fields.month.valueOf", + "call fields.month.valueOf", + "get fields.monthCode", + "get fields.monthCode.toString", + "call fields.monthCode.toString", + "get fields.year", + "get fields.year.valueOf", + "call fields.year.valueOf", + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", +]; +const actual = []; + +const instance = new Temporal.Calendar("iso8601"); + +const fields = TemporalHelpers.propertyBagObserver(actual, { + year: 1.7, + month: 1.7, + monthCode: "M01", + day: 1.7, +}, "fields"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + overflow: "reject", +}, "options"); + +const result = instance.monthDayFromFields(fields, options); +TemporalHelpers.assertPlainMonthDay(result, "M01", 1, "monthDay result"); +assert.sameValue(result.getISOFields().calendar, "iso8601", "calendar slot should store a string"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js new file mode 100644 index 0000000000..072e99e3f7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js @@ -0,0 +1,68 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Temporal.Calendar.prototype.monthDayFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »). + 7. Let overflow be ? ToTemporalOverflow(options). + 8. Perform ? ISOResolveMonth(fields). + 9. Let result be ? ISOMonthDayFromFields(fields, overflow). + 10. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], "iso8601", result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); +const opt = { overflow: "constrain" }; + +let result = cal.monthDayFromFields({ year: 2021, month: 13, day: 1 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 1, "month 13 is constrained to 12"); + +result = cal.monthDayFromFields({ year: 2021, month: 999999, day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 999999 is constrained to 12 and day 500 is constrained to 31"); + +[-99999, -1, 0].forEach((month) => { + assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month, day: 1 }, opt), + `Month ${month} is out of range for 2021 even with overflow: constrain` + ); +}); + +TemporalHelpers.ISOMonths.forEach(({ month, monthCode, daysInMonth }) => { + const day = daysInMonth + 1; + + result = cal.monthDayFromFields({ month, day }, opt); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, + `day is constrained from ${day} to ${daysInMonth} in month ${month}`); + + result = cal.monthDayFromFields({ month, day: 9001 }, opt); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, + `day is constrained to ${daysInMonth} in month ${month}`); + + result = cal.monthDayFromFields({ monthCode, day }, opt); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, + `day is constrained from ${day} to ${daysInMonth} in monthCode ${monthCode}`); + + result = cal.monthDayFromFields({ monthCode, day: 9001 }, opt); + TemporalHelpers.assertPlainMonthDay(result, monthCode, daysInMonth, + `day is constrained to ${daysInMonth} in monthCode ${monthCode}`); +}); + +[ ["month", 2], ["monthCode", "M02"] ].forEach(([ name, value ]) => { + result = cal.monthDayFromFields({ year: 2020, [name]: value, day: 30 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M02", 29, `${name} ${value} is constrained to 29 in leap year 2020`); + + result = cal.monthDayFromFields({ year: 2021, [name]: value, day: 29 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M02", 28, `${name} ${value} is constrained to 28 in common year 2021`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js new file mode 100644 index 0000000000..b028e3fdfc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.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.calendar.prototype.monthdayfromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js new file mode 100644 index 0000000000..fbc8f9351a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js @@ -0,0 +1,65 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »). + 7. Let overflow be ? ToTemporalOverflow(options). + 8. Perform ? ISOResolveMonth(fields). + 9. Let result be ? ISOMonthDayFromFields(fields, overflow). + 10. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], "iso8601", result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.monthDayFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); + +[-1, 0, 32, 999].forEach((day) => { + assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: 12, day }, { overflow: "reject" }), + `Day ${day} is out of range for 2021-12 with overflow: reject` + ); + assert.throws( + RangeError, + () => cal.monthDayFromFields({ monthCode: "M12", day }, { overflow: "reject" }), + `Day ${day} is out of range for 2021-M12 with overflow: reject` + ); +}); + +TemporalHelpers.ISOMonths.forEach(({ month, monthCode, daysInMonth }) => { + const day = daysInMonth + 1; + assert.throws(RangeError, + () => cal.monthDayFromFields({ month, day }, { overflow: "reject" }), + `Day ${day} is out of range for month ${month} with overflow: reject`); + assert.throws(RangeError, + () => cal.monthDayFromFields({ monthCode, day }, { overflow: "reject" }), + `Day ${day} is out of range for monthCode ${monthCode} with overflow: reject`); +}); + +[ ["month", 2], ["monthCode", "M02"] ].forEach(([ name, value ]) => { + assert.throws(RangeError, + () => cal.monthDayFromFields({ year: 2020, [name]: value, day: 30 }, { overflow: "reject" }), + `Day 30 is out of range for ${name} ${value} in leap year 2020 with overflow: reject`); + assert.throws(RangeError, + () => cal.monthDayFromFields({ year: 2021, [name]: value, day: 29 }, { overflow: "reject" }), + `Day 29 is out of range for ${name} ${value} in common year 2021 with overflow: reject`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.js new file mode 100644 index 0000000000..a44b81623e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-undefined.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.calendar.prototype.monthdayfromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, { overflow: undefined }); +TemporalHelpers.assertPlainMonthDay(explicit, "M12", 2, "default overflow is constrain"); +const implicit = calendar.monthDayFromFields({ year: 2000, month: 15, day: 2 }, {}); +TemporalHelpers.assertPlainMonthDay(implicit, "M12", 2, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js new file mode 100644 index 0000000000..bd1622c3c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthdayfromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isomonthdayfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.monthdayfromfields step 6: + 6. Let _result_ be ? ISOMonthDayFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainMonthDay(result, "M05", 2, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/prop-desc.js new file mode 100644 index 0000000000..f19dfbb6b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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.calendar.prototype.monthdayfromfields +description: The "monthDayFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthDayFromFields, + "function", + "`typeof Calendar.prototype.monthDayFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthDayFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthDayFromFields/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/Calendar/prototype/monthsInYear/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..35c86dbff2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.monthsInYear(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..6f6e691a59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.monthsInYear(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/Calendar/prototype/monthsInYear/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..2fca9d4da2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.monthsInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..f6da9031af --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.monthsInYear(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-leap-second.js new file mode 100644 index 0000000000..ff7496e9b1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.monthsInYear(arg); +assert.sameValue( + result1, + 12, + "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.monthsInYear(arg); +assert.sameValue( + result2, + 12, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-number.js new file mode 100644 index 0000000000..2a99f73f8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.monthsInYear(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/Calendar/prototype/monthsInYear/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..b8ee4e933b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthsInYear(arg); +assert.sameValue(result, 12, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..0d6c0d6ef4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthsInYear(arg); +assert.sameValue( + result, + 12, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..a0f70626e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.monthsInYear(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..460a47804c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.monthsInYear(arg); +assert.sameValue(result, 12, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..2b01fe1a0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + +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.monthsInYear(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.monthsInYear(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/Calendar/prototype/monthsInYear/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..c05540c245 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..0ee2a148c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.monthsInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..3612b56cf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthsInYear(arg); + + assert.sameValue( + result, + 12, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..578dc6f78a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..5b5536623f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.monthsInYear(arg); + + assert.sameValue( + result, + 12, + `"${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.monthsInYear(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js new file mode 100644 index 0000000000..fc2949e0c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..0be9d3322c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..76d6a2889f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-separators.js new file mode 100644 index 0000000000..05b17c402e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthsInYear(arg); + + assert.sameValue( + result, + 12, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..dd25899d21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.monthsinyear +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthsInYear(arg); + + assert.sameValue( + result, + 12, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..bb7b7ee3f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.monthsInYear(arg); + + assert.sameValue( + result, + 12, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..1d40c304b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(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/Calendar/prototype/monthsInYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js new file mode 100644 index 0000000000..ef3a529db2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: An ISO 8601 date string should be converted as input +info: | + a. Perform ? ToTemporalDate(temporalDateLike). + 5. Return 12𝔽. +features: [Temporal] +---*/ + +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.monthsInYear("3456-12-20"), 12); +assert.sameValue(cal.monthsInYear("+000998-01-28"), 12); +assert.sameValue(cal.monthsInYear("3456-12-20T03:04:05+00:00[UTC]"), 12); +assert.sameValue(cal.monthsInYear("+000998-01-28T03:04:05+00:00[UTC]"), 12); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-wrong-type.js new file mode 100644 index 0000000000..bbe7c6bec4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + +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.monthsInYear(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.monthsInYear(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/Calendar/prototype/monthsInYear/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..63120471a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.monthsInYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..e937a035ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +instance.monthsInYear(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..a49579b197 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..aced8bc1b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.monthsInYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..5a1618fd50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..794fa1edd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.monthsInYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js new file mode 100644 index 0000000000..a74818422a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.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.calendar.prototype.monthsinyear +description: Basic tests for monthsInYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 12; +assert.sameValue(iso.monthsInYear(new Temporal.PlainDate(1994, 11, 5)), res, "PlainDate"); +assert.sameValue(iso.monthsInYear(new Temporal.PlainDateTime(1994, 11, 5, 8, 15, 30)), res, "PlainDateTime"); +assert.sameValue(iso.monthsInYear(new Temporal.PlainYearMonth(1994, 11)), res, "PlainYearMonth"); +assert.sameValue(iso.monthsInYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.monthsInYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.monthsInYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js new file mode 100644 index 0000000000..f0733876d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const monthsInYear = Temporal.Calendar.prototype.monthsInYear; + +assert.sameValue(typeof monthsInYear, "function"); + +const args = [new Temporal.PlainDate(2021, 3, 4)]; + +assert.throws(TypeError, () => monthsInYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => monthsInYear.apply(null, args), "null"); +assert.throws(TypeError, () => monthsInYear.apply(true, args), "true"); +assert.throws(TypeError, () => monthsInYear.apply("", args), "empty string"); +assert.throws(TypeError, () => monthsInYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => monthsInYear.apply(1, args), "1"); +assert.throws(TypeError, () => monthsInYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => monthsInYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => monthsInYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/builtin.js new file mode 100644 index 0000000000..66ec0ebe99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: > + Tests that Temporal.Calendar.prototype.monthsInYear + 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.Calendar.prototype.monthsInYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.monthsInYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.monthsInYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.monthsInYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..416cc559a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +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(); +calendar.monthsInYear({ 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/Calendar/prototype/monthsInYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js new file mode 100644 index 0000000000..80daa1bc7b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.monthsinyear step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.monthsInYear({ year: 2000, month: 5, 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/Calendar/prototype/monthsInYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-temporal-object.js new file mode 100644 index 0000000000..b65eff793b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.monthsinyear step 4: + 4. Perform ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.monthsInYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..d0937c3663 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.monthsInYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.monthsInYear({ ...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/Calendar/prototype/monthsInYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/length.js new file mode 100644 index 0000000000..14d9d9d9e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: Temporal.Calendar.prototype.monthsInYear.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.Calendar.prototype.monthsInYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/name.js new file mode 100644 index 0000000000..bb140c095e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: Temporal.Calendar.prototype.monthsInYear.name is "monthsInYear". +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.Calendar.prototype.monthsInYear, "name", { + value: "monthsInYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/not-a-constructor.js new file mode 100644 index 0000000000..bf5940e1df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: > + Temporal.Calendar.prototype.monthsInYear 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.Calendar.prototype.monthsInYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.monthsInYear), false, + "isConstructor(Temporal.Calendar.prototype.monthsInYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/prop-desc.js new file mode 100644 index 0000000000..b6e58dea1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +description: The "monthsInYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.monthsInYear, + "function", + "`typeof Calendar.prototype.monthsInYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "monthsInYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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/Calendar/prototype/monthsInYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/year-zero.js new file mode 100644 index 0000000000..bb6d5c9da8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/monthsInYear/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.calendar.prototype.monthsinyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js new file mode 100644 index 0000000000..04b8e87d06 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-calendar-prototype +description: The "prototype" property of Temporal.Calendar +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.Calendar.prototype, "object"); +assert.notSameValue(Temporal.Calendar.prototype, null); + +verifyProperty(Temporal.Calendar, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js new file mode 100644 index 0000000000..3c0caacf81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toJSON = Temporal.Calendar.prototype.toJSON; + +assert.sameValue(typeof toJSON, "function"); + +assert.throws(TypeError, () => toJSON.call(undefined), "undefined"); +assert.throws(TypeError, () => toJSON.call(null), "null"); +assert.throws(TypeError, () => toJSON.call(true), "true"); +assert.throws(TypeError, () => toJSON.call(""), "empty string"); +assert.throws(TypeError, () => toJSON.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toJSON.call(1), "1"); +assert.throws(TypeError, () => toJSON.call({}), "plain object"); +assert.throws(TypeError, () => toJSON.call(Temporal.Calendar), "Temporal.Calendar"); +assert.throws(TypeError, () => toJSON.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js new file mode 100644 index 0000000000..21a148167a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: > + Tests that Temporal.Calendar.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js new file mode 100644 index 0000000000..7328585d32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Temporal.Calendar.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js new file mode 100644 index 0000000000..15a3bf26bf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: Temporal.Calendar.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js new file mode 100644 index 0000000000..fa6dd3872a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: > + Temporal.Calendar.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.toJSON), false, + "isConstructor(Temporal.Calendar.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js new file mode 100644 index 0000000000..8b0e819c89 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tojson +description: The "toJSON" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.toJSON, + "function", + "`typeof Calendar.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/returns-identifier-slot.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/returns-identifier-slot.js new file mode 100644 index 0000000000..297b066c40 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/returns-identifier-slot.js @@ -0,0 +1,26 @@ +// |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.calendar.prototype.tojson +description: toJSON() returns the internal slot value +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.observeProperty(actual, calendar, Symbol.toPrimitive, undefined); +TemporalHelpers.observeProperty(actual, calendar, "id", "bogus"); +TemporalHelpers.observeProperty(actual, calendar, "toString", function () { + actual.push("call calendar.toString"); + return "gregory"; +}); + +const result = calendar.toJSON(); +assert.sameValue(result, "iso8601", "toJSON gets the internal slot value"); +assert.compareArray(actual, [], "should not invoke any observable operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toJSON/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/branding.js new file mode 100644 index 0000000000..947edcb284 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toString = Temporal.Calendar.prototype.toString; + +assert.sameValue(typeof toString, "function"); + +assert.throws(TypeError, () => toString.call(undefined), "undefined"); +assert.throws(TypeError, () => toString.call(null), "null"); +assert.throws(TypeError, () => toString.call(true), "true"); +assert.throws(TypeError, () => toString.call(""), "empty string"); +assert.throws(TypeError, () => toString.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toString.call(1), "1"); +assert.throws(TypeError, () => toString.call({}), "plain object"); +assert.throws(TypeError, () => toString.call(Temporal.Calendar), "Temporal.Calendar"); +assert.throws(TypeError, () => toString.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js new file mode 100644 index 0000000000..6f0e53c4d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: > + Tests that Temporal.Calendar.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.Calendar.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js new file mode 100644 index 0000000000..00c4b7f57f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: Temporal.Calendar.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js new file mode 100644 index 0000000000..b5268eef32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: Temporal.Calendar.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js new file mode 100644 index 0000000000..03f2a139ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: > + Temporal.Calendar.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.Calendar.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.toString), false, + "isConstructor(Temporal.Calendar.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js new file mode 100644 index 0000000000..d0b3d53e99 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.tostring +description: The "toString" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.toString, + "function", + "`typeof Calendar.prototype.toString` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toString/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/prop-desc.js new file mode 100644 index 0000000000..9ef3a23e21 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype-@@tostringtag +description: The @@toStringTag property of Temporal.Calendar +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.Calendar.prototype, Symbol.toStringTag, { + value: "Temporal.Calendar", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..fd0e559c7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.weekOfYear(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..2e3ae9291d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.weekOfYear(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/Calendar/prototype/weekOfYear/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..24b26e1281 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.weekOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..cc1de124c3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.weekOfYear(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-leap-second.js new file mode 100644 index 0000000000..00140dd078 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.weekOfYear(arg); +assert.sameValue( + result1, + 52, + "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.weekOfYear(arg); +assert.sameValue( + result2, + 52, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-number.js new file mode 100644 index 0000000000..d631e5fe18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.weekOfYear(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/Calendar/prototype/weekOfYear/argument-plaindate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js new file mode 100644 index 0000000000..b7fda66665 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js @@ -0,0 +1,79 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take Temporal.PlainDate object + and return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +let d = new Temporal.PlainDate(1977, 1, 1); +assert.sameValue(cal.weekOfYear(d), 53, "1977-01-01 is in w53"); + +d = new Temporal.PlainDate(1977, 1, 2); +assert.sameValue(cal.weekOfYear(d), 53, "1977-01-02 is in w53"); + +d = new Temporal.PlainDate(1977, 12, 31); +assert.sameValue(cal.weekOfYear(d), 52, "1977-12-31 is in w52"); + +d = new Temporal.PlainDate(1978, 1, 1); +assert.sameValue(cal.weekOfYear(d), 52, "1978-01-01 is in w52"); + +d = new Temporal.PlainDate(1978, 1, 2); +assert.sameValue(cal.weekOfYear(d), 1, "1978-01-02 is in w01"); + +d = new Temporal.PlainDate(1978, 12, 31); +assert.sameValue(cal.weekOfYear(d), 52, "1978-12-31 is in w52"); + +d = new Temporal.PlainDate(1979, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1979-01-01 is in w01"); + +d = new Temporal.PlainDate(1979, 12, 30); +assert.sameValue(cal.weekOfYear(d), 52, "1979-12-30 is in w52"); + +d = new Temporal.PlainDate(1979, 12, 31); +assert.sameValue(cal.weekOfYear(d), 1, "1979-12-31 is in w01"); + +d = new Temporal.PlainDate(1980, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1980-01-01 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 28); +assert.sameValue(cal.weekOfYear(d), 52, "1980-12-28 is in w52"); + +d = new Temporal.PlainDate(1980, 12, 29); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-29 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 30); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-30 is in w01"); + +d = new Temporal.PlainDate(1980, 12, 31); +assert.sameValue(cal.weekOfYear(d), 1, "1980-12-31 is in w01"); + +d = new Temporal.PlainDate(1981, 1, 1); +assert.sameValue(cal.weekOfYear(d), 1, "1981-01-01 is in w01"); + +d = new Temporal.PlainDate(1981, 12, 31); +assert.sameValue(cal.weekOfYear(d), 53, "1981-12-31 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 1); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-01 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 2); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-02 is in w53"); + +d = new Temporal.PlainDate(1982, 1, 3); +assert.sameValue(cal.weekOfYear(d), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js new file mode 100644 index 0000000000..b92cd47f7e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js @@ -0,0 +1,79 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take Temporal.PlainDateTime object + and return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +let dt = new Temporal.PlainDateTime(1977, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1977-01-01 is in w53"); + +dt = new Temporal.PlainDateTime(1977, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1977-01-02 is in w53"); + +dt = new Temporal.PlainDateTime(1977, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1977-12-31 is in w52"); + +dt = new Temporal.PlainDateTime(1978, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1978-01-01 is in w52"); + +dt = new Temporal.PlainDateTime(1978, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1978-01-02 is in w01"); + +dt = new Temporal.PlainDateTime(1978, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1978-12-31 is in w52"); + +dt = new Temporal.PlainDateTime(1979, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1979-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1979, 12, 30, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1979-12-30 is in w52"); + +dt = new Temporal.PlainDateTime(1979, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1979-12-31 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 28, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 52, "1980-12-28 is in w52"); + +dt = new Temporal.PlainDateTime(1980, 12, 29, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-29 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 30, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-30 is in w01"); + +dt = new Temporal.PlainDateTime(1980, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1980-12-31 is in w01"); + +dt = new Temporal.PlainDateTime(1981, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 1, "1981-01-01 is in w01"); + +dt = new Temporal.PlainDateTime(1981, 12, 31, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1981-12-31 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 1, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-01 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 2, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-02 is in w53"); + +dt = new Temporal.PlainDateTime(1982, 1, 3, 9, 8); +assert.sameValue(cal.weekOfYear(dt), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..5970881125 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.weekOfYear(arg); +assert.sameValue(result, 47, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..787d8c128e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.weekOfYear(arg); +assert.sameValue( + result, + 47, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..cb4c271731 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.weekOfYear(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..ca01bb614b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.weekOfYear(arg); +assert.sameValue(result, 47, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..9c70b5e3fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + +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.weekOfYear(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.weekOfYear(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/Calendar/prototype/weekOfYear/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..023b2ca730 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..d0ef9a8fd8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.weekOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..89d3de01b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.weekOfYear(arg); + + assert.sameValue( + result, + 18, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..c031c1d9f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..caf708e268 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.weekOfYear(arg); + + assert.sameValue( + result, + 18, + `"${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.weekOfYear(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js new file mode 100644 index 0000000000..9325337841 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..9cc6e3b820 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..72ff52c876 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-separators.js new file mode 100644 index 0000000000..7a6839eee8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.weekOfYear(arg); + + assert.sameValue( + result, + 18, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..86332e48bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.weekofyear +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.weekOfYear(arg); + + assert.sameValue( + result, + 18, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..9f91ef3d31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.weekOfYear(arg); + + assert.sameValue( + result, + 18, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..f7fc0c82b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(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/Calendar/prototype/weekOfYear/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js new file mode 100644 index 0000000000..0a7b4b90d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear will take an ISO 8601 date string and + return the week of year of that date. +info: | + 4. Let temporalDate be ? ToTemporalDate(temporalDateLike). + 5. Return 𝔽(! ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week numbers are taken from the table "Examples of contemporary +// dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +assert.sameValue(cal.weekOfYear("1977-01-01"), 53, "1977-01-01 is in w53"); +assert.sameValue(cal.weekOfYear("1977-01-02"), 53, "1977-01-02 is in w53"); +assert.sameValue(cal.weekOfYear("1977-12-31"), 52, "1977-12-31 is in w52"); +assert.sameValue(cal.weekOfYear("1978-01-01"), 52, "1978-01-01 is in w52"); +assert.sameValue(cal.weekOfYear("1978-01-02"), 1, "1978-01-02 is in w01"); +assert.sameValue(cal.weekOfYear("1978-12-31"), 52, "1978-12-31 is in w52"); +assert.sameValue(cal.weekOfYear("1979-01-01"), 1, "1979-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1979-12-30"), 52, "1979-12-30 is in w52"); +assert.sameValue(cal.weekOfYear("1979-12-31"), 1, "1979-12-31 is in w01"); +assert.sameValue(cal.weekOfYear("1980-01-01"), 1, "1980-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-28"), 52, "1980-12-28 is in w52"); +assert.sameValue(cal.weekOfYear("1980-12-29"), 1, "1980-12-29 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-30"), 1, "1980-12-30 is in w01"); +assert.sameValue(cal.weekOfYear("1980-12-31"), 1, "1980-12-31 is in w01"); +assert.sameValue(cal.weekOfYear("1981-01-01"), 1, "1981-01-01 is in w01"); +assert.sameValue(cal.weekOfYear("1981-12-31"), 53, "1981-12-31 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-01"), 53, "1982-01-01 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-02"), 53, "1982-01-02 is in w53"); +assert.sameValue(cal.weekOfYear("1982-01-03"), 53, "1982-01-03 is in w53"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-wrong-type.js new file mode 100644 index 0000000000..85aedab4fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + +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.weekOfYear(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.weekOfYear(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/Calendar/prototype/weekOfYear/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..60bc7f87ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.weekOfYear(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..f88b773cf7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +instance.weekOfYear(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..5476520dbc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..49cfdd2577 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.weekOfYear(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..546d44e176 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..72f5d659de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.weekOfYear(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.js new file mode 100644 index 0000000000..1eb5ea7100 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/basic.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.calendar.prototype.weekofyear +description: Basic tests for weekOfYear(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 44; +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.weekOfYear({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.weekOfYear("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.weekOfYear({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js new file mode 100644 index 0000000000..ee012dbfa8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const weekOfYear = Temporal.Calendar.prototype.weekOfYear; + +assert.sameValue(typeof weekOfYear, "function"); + +const args = [new Temporal.PlainDate(2021, 7, 20)]; + +assert.throws(TypeError, () => weekOfYear.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => weekOfYear.apply(null, args), "null"); +assert.throws(TypeError, () => weekOfYear.apply(true, args), "true"); +assert.throws(TypeError, () => weekOfYear.apply("", args), "empty string"); +assert.throws(TypeError, () => weekOfYear.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => weekOfYear.apply(1, args), "1"); +assert.throws(TypeError, () => weekOfYear.apply({}, args), "plain object"); +assert.throws(TypeError, () => weekOfYear.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => weekOfYear.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/builtin.js new file mode 100644 index 0000000000..9a59d31cc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: > + Tests that Temporal.Calendar.prototype.weekOfYear + 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.Calendar.prototype.weekOfYear), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.weekOfYear), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.weekOfYear), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.weekOfYear.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..f4259f0eb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +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(); +calendar.weekOfYear({ 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/Calendar/prototype/weekOfYear/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js new file mode 100644 index 0000000000..b243c771e7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-fields-iterable.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.weekofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.weekOfYear({ year: 2000, month: 5, 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/Calendar/prototype/weekOfYear/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-temporal-object.js new file mode 100644 index 0000000000..3f2769d5b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.weekofyear step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.weekOfYear({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js new file mode 100644 index 0000000000..d65ef91a26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/cross-year.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: weekOfYear() crossing year boundaries. +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("2019-12-31")), 1, "week 1 from next year"); +assert.sameValue(iso.weekOfYear(Temporal.PlainDate.from("2021-01-01")), 53, "week 1 from next year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..f1724eb32d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.weekOfYear({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.weekOfYear({ ...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/Calendar/prototype/weekOfYear/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/length.js new file mode 100644 index 0000000000..97c6fb0a30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: Temporal.Calendar.prototype.weekOfYear.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.Calendar.prototype.weekOfYear, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/name.js new file mode 100644 index 0000000000..91d4d267a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: Temporal.Calendar.prototype.weekOfYear.name is "weekOfYear". +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.Calendar.prototype.weekOfYear, "name", { + value: "weekOfYear", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/not-a-constructor.js new file mode 100644 index 0000000000..21889a2671 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: > + Temporal.Calendar.prototype.weekOfYear 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.Calendar.prototype.weekOfYear(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.weekOfYear), false, + "isConstructor(Temporal.Calendar.prototype.weekOfYear)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/prop-desc.js new file mode 100644 index 0000000000..31a0f5e4fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +description: The "weekOfYear" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.weekOfYear, + "function", + "`typeof Calendar.prototype.weekOfYear` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "weekOfYear", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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/Calendar/prototype/weekOfYear/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/year-zero.js new file mode 100644 index 0000000000..e027bfca5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/weekOfYear/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.calendar.prototype.weekofyear +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..ca4afbce33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.year(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..c5b697a625 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.year(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/Calendar/prototype/year/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..cbf629b522 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.year(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..d9ef764654 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.year(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-leap-second.js new file mode 100644 index 0000000000..ed9d642ec9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.year(arg); +assert.sameValue( + result1, + 2016, + "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.year(arg); +assert.sameValue( + result2, + 2016, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-number.js new file mode 100644 index 0000000000..109a5ff177 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.year(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/Calendar/prototype/year/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..c0eb531ee1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.year(arg); +assert.sameValue(result, 1976, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..6079a33b9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.year(arg); +assert.sameValue( + result, + 1976, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..7ab6fa7b56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.year(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..ebd1c87cb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.year(arg); +assert.sameValue(result, 1976, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..803b29f747 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + +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.year(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.year(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/Calendar/prototype/year/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..742326e600 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..9f3120fdcd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.year(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..b43409dfec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.year(arg); + + assert.sameValue( + result, + 2000, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..054e3e1151 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..a8d1259e03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.year(arg); + + assert.sameValue( + result, + 2000, + `"${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.year(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js new file mode 100644 index 0000000000..625844661f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.year(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..41f297f57e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..f1f47b87b7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-separators.js new file mode 100644 index 0000000000..ee9b15226c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.year(arg); + + assert.sameValue( + result, + 2000, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..144b514253 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.year +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.year(arg); + + assert.sameValue( + result, + 2000, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..b95e97476c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.year(arg); + + assert.sameValue( + result, + 2000, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..3f690f9936 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(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/Calendar/prototype/year/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-wrong-type.js new file mode 100644 index 0000000000..dbce82cb1f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + +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.year(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.year(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/Calendar/prototype/year/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..575167a02e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.year(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..c3221920bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +instance.year(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..71aef5ef62 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..fd036d070c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.year(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..5b11ad3a9c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..071389f0ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.year(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.js new file mode 100644 index 0000000000..65bc6c05c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/basic.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.calendar.prototype.year +description: Basic tests for year(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 1994; +assert.sameValue(iso.year(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.year(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.year(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +assert.sameValue(iso.year({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.year("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.year({ month: 5 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/branding.js new file mode 100644 index 0000000000..a0d24974fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const year = Temporal.Calendar.prototype.year; + +assert.sameValue(typeof year, "function"); + +const args = [new Temporal.PlainDate(2000, 1, 1)]; + +assert.throws(TypeError, () => year.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => year.apply(null, args), "null"); +assert.throws(TypeError, () => year.apply(true, args), "true"); +assert.throws(TypeError, () => year.apply("", args), "empty string"); +assert.throws(TypeError, () => year.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => year.apply(1, args), "1"); +assert.throws(TypeError, () => year.apply({}, args), "plain object"); +assert.throws(TypeError, () => year.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => year.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/builtin.js new file mode 100644 index 0000000000..8f6eda4a10 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: > + Tests that Temporal.Calendar.prototype.year + 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.Calendar.prototype.year), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.year), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.year), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.year.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..f2b94e2c0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +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(); +calendar.year({ 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/Calendar/prototype/year/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js new file mode 100644 index 0000000000..eb5babfc8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-fields-iterable.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.year step 4: + 4. Return ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.year({ year: 2000, month: 5, 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/Calendar/prototype/year/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js new file mode 100644 index 0000000000..6e1edc8bb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/calendar-temporal-object.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.year step 4: + 4. Return ? ISOYear(_dateOrDateTime_). + sec-temporal-isoyear step 1.a: + a. Set _dateOrDateTime_ to ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.year({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js new file mode 100644 index 0000000000..79d01e7c59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date-time.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year will take PlainDateTime and return + the value of the year. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISOYear(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let dateTime = new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13) +assert.sameValue(cal.year(dateTime), 1997, 'cal.year(new Temporal.PlainDateTime(1997, 8, 23, 5, 30, 13)) must return 1997'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js new file mode 100644 index 0000000000..22a7117552 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/date.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year will take PlainDate and return + the value of the year. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISOYear(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let date = new Temporal.PlainDate(2021, 7, 15); +assert.sameValue(cal.year(date), 2021, 'cal.year(new Temporal.PlainDate(2021, 7, 15)) must return 2021'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..e8cfec61d6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.year({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.year({ ...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/Calendar/prototype/year/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/length.js new file mode 100644 index 0000000000..7e336f251c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: Temporal.Calendar.prototype.year.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.Calendar.prototype.year, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/name.js new file mode 100644 index 0000000000..a7205e1c1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: Temporal.Calendar.prototype.year.name is "year". +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.Calendar.prototype.year, "name", { + value: "year", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/not-a-constructor.js new file mode 100644 index 0000000000..f1a6e11107 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year 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.Calendar.prototype.year(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.year), false, + "isConstructor(Temporal.Calendar.prototype.year)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/prop-desc.js new file mode 100644 index 0000000000..d6caba2847 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +description: The "year" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.year, + "function", + "`typeof Calendar.prototype.year` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "year", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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/Calendar/prototype/year/string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js new file mode 100644 index 0000000000..4774f958ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/string.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year will take ISO8601 string and return + the value of the year. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISOYear(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.sameValue(cal.year("2019-03-15"), 2019, 'cal.year("2019-03-15") must return 2019'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js new file mode 100644 index 0000000000..fa86c42a0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/throw-range-error-ToTemporalDate.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year throws RangeError on + ToTemporalDate when temporalDateLike is invalid string. +info: | + 4. If Type(temporalDateLike) is not Object or temporalDateLike + does not have an [[InitializedTemporalDate]] or + [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). +features: [Temporal, arrow-function] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +assert.throws(RangeError, () => cal.year("invalid string"), + 'cal.year("invalid string") throws a RangeError exception'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js new file mode 100644 index 0000000000..dfa6c299f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-month.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + Temporal.Calendar.prototype.year will take PlainYearMonth and return + the value of the year. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]] or [[InitializedTemporalYearMonth]] internal slot, then + a. Set temporalDateLike to ? ToTemporalDate(temporalDateLike). + 5. Return ! ISOYear(temporalDateLike). +features: [Temporal] +---*/ +let cal = new Temporal.Calendar("iso8601"); + +let yearMonth = new Temporal.PlainYearMonth(1999, 6); +assert.sameValue(cal.year(yearMonth), 1999, 'cal.year(new Temporal.PlainYearMonth(1999, 6)) must return 1999'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/year-zero.js new file mode 100644 index 0000000000..2185c1b630 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/year/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.calendar.prototype.year +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.year(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js new file mode 100644 index 0000000000..65e6b5888f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +let result = cal.yearMonthFromFields({ year: 2021, month: 7 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, month 7"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, month 12"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, monthCode M07"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, monthCode M12"); + +["constrain", "reject"].forEach((overflow) => { + const opt = { overflow }; + result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, month 7, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, month 12, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, monthCode M07, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, monthCode M12, overflow ${overflow}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js new file mode 100644 index 0000000000..62dd196840 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const yearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; + +assert.sameValue(typeof yearMonthFromFields, "function"); + +const args = [{ year: 2021, month: 1 }]; + +assert.throws(TypeError, () => yearMonthFromFields.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => yearMonthFromFields.apply(null, args), "null"); +assert.throws(TypeError, () => yearMonthFromFields.apply(true, args), "true"); +assert.throws(TypeError, () => yearMonthFromFields.apply("", args), "empty string"); +assert.throws(TypeError, () => yearMonthFromFields.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => yearMonthFromFields.apply(1, args), "1"); +assert.throws(TypeError, () => yearMonthFromFields.apply({}, args), "plain object"); +assert.throws(TypeError, () => yearMonthFromFields.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => yearMonthFromFields.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/builtin.js new file mode 100644 index 0000000000..0de5aad315 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: > + Tests that Temporal.Calendar.prototype.yearMonthFromFields + 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.Calendar.prototype.yearMonthFromFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.yearMonthFromFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.yearMonthFromFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.yearMonthFromFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js new file mode 100644 index 0000000000..528ea2998e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.yearMonthFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ month: 1 }), "year is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ year: 2021 }), "month or monthCode is required"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js new file mode 100644 index 0000000000..a8af3e6628 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.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.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if the fields is not an object +features: [Symbol, Temporal] +---*/ + +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = Temporal.Calendar.from("iso8601"); +for (const fields of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields(fields, {})); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..7c7f33f3a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/infinity-throws-rangeerror.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. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.yearmonthfromfields +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.yearMonthFromFields({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/length.js new file mode 100644 index 0000000000..b87ac41bb3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields.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.Calendar.prototype.yearMonthFromFields, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/missing-properties.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/missing-properties.js new file mode 100644 index 0000000000..9de556a653 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/missing-properties.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Errors due to missing properties on fields object are thrown in the correct order +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let getMonth = false; +let getMonthCode = false; +const missingYearAndMonth = { + get month() { + getMonth = true; + }, + get monthCode() { + getMonthCode = true; + }, +}; +assert.throws(TypeError, () => instance.yearMonthFromFields(missingYearAndMonth), "year should be checked after fetching but before resolving the month"); +assert(getMonth, "year is fetched after month"); +assert(getMonthCode, "year is fetched after monthCode"); + +assert.throws(TypeError, () => instance.yearMonthFromFields({ year: 2000 }), "month should be resolved last"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js new file mode 100644 index 0000000000..41ca759058 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, month: 12, monthCode: "M11" }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not valid for year 2021`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/name.js new file mode 100644 index 0000000000..70c404a728 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields.name is "yearMonthFromFields". +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.Calendar.prototype.yearMonthFromFields, "name", { + value: "yearMonthFromFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/not-a-constructor.js new file mode 100644 index 0000000000..58c175cb8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: > + Temporal.Calendar.prototype.yearMonthFromFields 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.Calendar.prototype.yearMonthFromFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.yearMonthFromFields), false, + "isConstructor(Temporal.Calendar.prototype.yearMonthFromFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/one-of-era-erayear-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/one-of-era-erayear-undefined.js new file mode 100644 index 0000000000..6696311237 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/one-of-era-erayear-undefined.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.calendar.prototype.yearMonthFromFields +description: Does not throw a RangeError if only one of era/eraYear fields is present +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const base = { year: 2000, month: 5, day: 2, era: 'ce' }; +const instance = new Temporal.Calendar('iso8601'); +TemporalHelpers.assertPlainYearMonth(instance.yearMonthFromFields({ ...base }), 2000, 5, 'M05'); + +const base2 = { year: 2000, month: 5, day: 2, eraYear: 1 }; +TemporalHelpers.assertPlainYearMonth(instance.yearMonthFromFields({ ...base }), 2000, 5, 'M05'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js new file mode 100644 index 0000000000..65df607e7f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if options is not an object or undefined +info: | + 5. Set options to ? GetOptionsObject(options). +features: [Symbol, Temporal] +---*/ + +const tests = [null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = new Temporal.Calendar("iso8601"); +for (const options of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields({ year: 2021, month: 7 }, options), + "options is not object"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-object.js new file mode 100644 index 0000000000..4fc1e15706 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const result1 = instance.yearMonthFromFields({ year: 2000, monthCode: "M05" }, {}); +TemporalHelpers.assertPlainYearMonth( + result1, 2000, 5, "M05", + "options may be an empty plain object" +); + +const result2 = instance.yearMonthFromFields({ year: 2000, monthCode: "M05" }, () => {}); +TemporalHelpers.assertPlainYearMonth( + result2, 2000, 5, "M05", + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.js new file mode 100644 index 0000000000..4c0d750067 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +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.Calendar("iso8601"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.yearMonthFromFields({ year: 2000, monthCode: "M05" }, value), + `TypeError on wrong options type ${typeof value}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/order-of-operations.js new file mode 100644 index 0000000000..f66a3915a5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/order-of-operations.js @@ -0,0 +1,45 @@ +// |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.calendar.prototype.yearmonthfromfields +description: Properties on objects passed to yearMonthFromFields() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get fields.month", + "get fields.month.valueOf", + "call fields.month.valueOf", + "get fields.monthCode", + "get fields.monthCode.toString", + "call fields.monthCode.toString", + "get fields.year", + "get fields.year.valueOf", + "call fields.year.valueOf", + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", +]; +const actual = []; + +const instance = new Temporal.Calendar("iso8601"); + +const fields = TemporalHelpers.propertyBagObserver(actual, { + year: 1.7, + month: 1.7, + monthCode: "M01", +}, "fields"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + overflow: "reject", +}, "options"); + +const result = instance.yearMonthFromFields(fields, options); +TemporalHelpers.assertPlainYearMonth(result, 1, 1, "M01", "yearMonth result"); +assert.sameValue(result.getISOFields().calendar, "iso8601", "calendar slot should store a string"); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js new file mode 100644 index 0000000000..8a7a1b1ee2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js @@ -0,0 +1,94 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") +const opt = { overflow: "constrain" }; + +let result = cal.yearMonthFromFields({ year: 2021, month: 1 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "month 1 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 2 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "month 2 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 3 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "month 3 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 4 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "month 4 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 5 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "month 5 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 6 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "month 6 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "month 7 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 8 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "month 8 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 9 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "month 9 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 10 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "month 10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 11 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "month 11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 12 with overflow constrain"); + +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -99999 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: 0 }, opt), + "month zero is out of range even with overflow constrain" +) + +result = cal.yearMonthFromFields({ year: 2021, month: 13 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 13 is constrained to 12"); +result = cal.yearMonthFromFields({ year: 2021, month: 99999 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 99999 is constrained to 12"); + +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M01" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "monthCode M01 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M02" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "monthCode M02 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M03" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "monthCode M03 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M04" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "monthCode M04 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M05" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "monthCode M05 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M06" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "monthCode M06 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "monthCode M07 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M08" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "monthCode M08 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M09" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "monthCode M09 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M10" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "monthCode M10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M11" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "monthCode M11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "monthCode M12 with overflow constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js new file mode 100644 index 0000000000..db60f50816 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.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.calendar.prototype.yearmonthfromfields +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js new file mode 100644 index 0000000000..8c0e3efb27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.yearMonthFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.js new file mode 100644 index 0000000000..fe8e825846 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-undefined.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.calendar.prototype.yearmonthfromfields +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); + +const explicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, { overflow: undefined }); +TemporalHelpers.assertPlainYearMonth(explicit, 2000, 12, "M12", "default overflow is constrain"); +const implicit = calendar.yearMonthFromFields({ year: 2000, month: 15 }, {}); +TemporalHelpers.assertPlainYearMonth(implicit, 2000, 12, "M12", "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js new file mode 100644 index 0000000000..422e9cc007 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal-isoyearmonthfromfields step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). + sec-temporal.calendar.prototype.yearmonthfromfields step 6: + 6. Let _result_ be ? ISOYearMonthFromFields(_fields_, _options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainYearMonth(result, 2000, 5, "M05", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/prop-desc.js new file mode 100644 index 0000000000..b805c816df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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.calendar.prototype.yearmonthfromfields +description: The "yearMonthFromFields" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.yearMonthFromFields, + "function", + "`typeof Calendar.prototype.yearMonthFromFields` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "yearMonthFromFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/reference-day.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/reference-day.js new file mode 100644 index 0000000000..5c1157cda8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/reference-day.js @@ -0,0 +1,41 @@ +// |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.calendar.prototype.yearmonthfromfields +description: Reference ISO day is chosen to be the first of the calendar month +info: | + 6.d. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, *1*<sub>𝔽</sub>). + e. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +const result1 = cal.yearMonthFromFields({ year: 2023, monthCode: "M01", day: 13 }); +TemporalHelpers.assertPlainYearMonth( + result1, + 2023, 1, "M01", + "reference day is 1 even if day is given", + /* era = */ undefined, /* era year = */ undefined, /* reference day = */ 1 +); + +const result2 = cal.yearMonthFromFields({ year: 2021, monthCode: "M02", day: 50 }, { overflow: "constrain" }); +TemporalHelpers.assertPlainYearMonth( + result2, + 2021, 2, "M02", + "reference day is 1 even if day is out of range (overflow constrain)", + /* era = */ undefined, /* era year = */ undefined, /* reference day = */ 1 +); + +const result3 = cal.yearMonthFromFields({ year: 2021, monthCode: "M02", day: 50 }, { overflow: "reject" }); +TemporalHelpers.assertPlainYearMonth( + result3, + 2021, 2, "M02", + "reference day is 1 even if day is out of range (overflow reject)", + /* era = */ undefined, /* era year = */ undefined, /* reference day = */ 1 +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/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/Calendar/prototype/yearOfWeek/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..7ec569149d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.yearOfWeek(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..3fa5c6e13f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..ce63ac519f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.yearOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..d564d1f73f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + + assert.throws(RangeError, () => instance.yearOfWeek(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js new file mode 100644 index 0000000000..1e28b31f7c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.yearOfWeek(arg); +assert.sameValue( + result1, + 2016, + "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.yearOfWeek(arg); +assert.sameValue( + result2, + 2016, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-number.js new file mode 100644 index 0000000000..6e3a05779d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..208f4f763f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.yearOfWeek(arg); +assert.sameValue(result, 1976, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..fb54865fc1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.yearOfWeek(arg); +assert.sameValue( + result, + 1976, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..c74d13eb85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.yearOfWeek(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..686ec25927 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.yearOfWeek(arg); +assert.sameValue(result, 1976, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..e05f76a918 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + +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.yearOfWeek(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.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..ad33245788 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..48e0ff8e18 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + +assert.throws(RangeError, () => instance.yearOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..e278468ad2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..1feab2ed81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..38836a243e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +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.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `"${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.yearOfWeek(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-invalid.js new file mode 100644 index 0000000000..b93efa8ca6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..f584787616 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..559c84c38c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js new file mode 100644 index 0000000000..19820a2a93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..8cfe78c092 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |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.calendar.prototype.yearofweek +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..7778eec61f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +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.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..bebc2b7b8c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-string.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string.js new file mode 100644 index 0000000000..100982120b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string.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.calendar.prototype.yearofweek +description: > + Temporal.Calendar.prototype.yearOfWeek will take an ISO 8601 date string and + return the ISO week calendar year of that date. +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +// The following week calendar years are taken from the table "Examples of +// contemporary dates around New Year's Day" from +// https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar + +assert.sameValue(cal.yearOfWeek("1977-01-01"), 1976, "1977-01-01 is in yearOfWeek 1976"); +assert.sameValue(cal.yearOfWeek("1977-01-02"), 1976, "1977-01-02 is in yearOfWeek 1976"); +assert.sameValue(cal.yearOfWeek("1977-12-31"), 1977, "1977-12-31 is in yearOfWeek 1977"); +assert.sameValue(cal.yearOfWeek("1978-01-01"), 1977, "1978-01-01 is in yearOfWeek 1977"); +assert.sameValue(cal.yearOfWeek("1978-01-02"), 1978, "1978-01-02 is in yearOfWeek 1978"); +assert.sameValue(cal.yearOfWeek("1978-12-31"), 1978, "1978-12-31 is in yearOfWeek 1978"); +assert.sameValue(cal.yearOfWeek("1979-01-01"), 1979, "1979-01-01 is in yearOfWeek 1979"); +assert.sameValue(cal.yearOfWeek("1979-12-30"), 1979, "1979-12-30 is in yearOfWeek 1979"); +assert.sameValue(cal.yearOfWeek("1979-12-31"), 1980, "1979-12-31 is in yearOfWeek 1980"); +assert.sameValue(cal.yearOfWeek("1980-01-01"), 1980, "1980-01-01 is in yearOfWeek 1980"); +assert.sameValue(cal.yearOfWeek("1980-12-28"), 1980, "1980-12-28 is in yearOfWeek 1980"); +assert.sameValue(cal.yearOfWeek("1980-12-29"), 1981, "1980-12-29 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1980-12-30"), 1981, "1980-12-30 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1980-12-31"), 1981, "1980-12-31 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1981-01-01"), 1981, "1981-01-01 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1981-12-31"), 1981, "1981-12-31 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1982-01-01"), 1981, "1982-01-01 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1982-01-02"), 1981, "1982-01-02 is in yearOfWeek 1981"); +assert.sameValue(cal.yearOfWeek("1982-01-03"), 1981, "1982-01-03 is in yearOfWeek 1981"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-wrong-type.js new file mode 100644 index 0000000000..9d872b2e35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + +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.yearOfWeek(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.yearOfWeek(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/Calendar/prototype/yearOfWeek/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..1e694bc160 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); + +assert.throws(Test262Error, () => instance.yearOfWeek(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..86f4d6326c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +instance.yearOfWeek(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..9277758fb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.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.calendar.prototype.yearofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.yearOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..f76c1b0ef3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => calendar.yearOfWeek(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..abdfc3a615 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => calendar.yearOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..2e48de6dbe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.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.calendar.prototype.yearofweek +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 calendar = new Temporal.Calendar("iso8601"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => calendar.yearOfWeek(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.js new file mode 100644 index 0000000000..6d003929f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.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.calendar.prototype.yearofweek +description: Basic tests for yearOfWeek(). +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +const res = 1994; +assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); +assert.sameValue(iso.yearOfWeek(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); +assert.sameValue(iso.yearOfWeek({ year: 1994, month: 11, day: 5 }), res, "property bag"); +assert.sameValue(iso.yearOfWeek("1994-11-05"), res, "string"); +assert.throws(TypeError, () => iso.yearOfWeek({ year: 2000 }), "property bag with missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.js new file mode 100644 index 0000000000..82cba7fbe4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.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.calendar.prototype.yearofweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const yearOfWeek = Temporal.Calendar.prototype.yearOfWeek; + +assert.sameValue(typeof yearOfWeek, "function"); + +const args = [new Temporal.PlainDate(2021, 7, 20)]; + +assert.throws(TypeError, () => yearOfWeek.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => yearOfWeek.apply(null, args), "null"); +assert.throws(TypeError, () => yearOfWeek.apply(true, args), "true"); +assert.throws(TypeError, () => yearOfWeek.apply("", args), "empty string"); +assert.throws(TypeError, () => yearOfWeek.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => yearOfWeek.apply(1, args), "1"); +assert.throws(TypeError, () => yearOfWeek.apply({}, args), "plain object"); +assert.throws(TypeError, () => yearOfWeek.apply(Temporal.Calendar, args), "Temporal.Calendar"); +assert.throws(TypeError, () => yearOfWeek.apply(Temporal.Calendar.prototype, args), "Temporal.Calendar.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/browser.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js new file mode 100644 index 0000000000..af26883b52 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js @@ -0,0 +1,36 @@ +// |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.calendar.prototype.yearofweek +description: > + Tests that Temporal.Calendar.prototype.yearOfWeek + 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.Calendar.prototype.yearOfWeek), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.Calendar.prototype.yearOfWeek), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.Calendar.prototype.yearOfWeek), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.Calendar.prototype.yearOfWeek.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..3fee75ad1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +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(); +calendar.yearOfWeek({ 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/Calendar/prototype/yearOfWeek/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-fields-iterable.js new file mode 100644 index 0000000000..a3d2aeb80f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-fields-iterable.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.calendar.prototype.yearofweek +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.calendar.prototype.yearofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 ? IterableToListOfType(_fieldsArray_, « String »). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const calendar1 = TemporalHelpers.calendarFieldsIterable(); +const calendar2 = TemporalHelpers.calendarFieldsIterable(); +calendar1.yearOfWeek({ year: 2000, month: 5, 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/Calendar/prototype/yearOfWeek/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-temporal-object.js new file mode 100644 index 0000000000..461137a7d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-temporal-object.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.calendar.prototype.yearofweek step 4: + 4. Let _date_ be ? ToTemporalDate(_dateOrDateTime_). + 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 calendar = new Temporal.Calendar("iso8601"); + calendar.yearOfWeek({ year: 2000, month: 5, day: 2, calendar: temporalObject }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js new file mode 100644 index 0000000000..1ca8d9baff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearOfWeek +description: yearOfWeek() where the result is different from the calendar year +features: [Temporal] +---*/ + +const iso = Temporal.Calendar.from("iso8601"); +assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("2019-12-31")), 2020, "next year"); +assert.sameValue(iso.yearOfWeek(Temporal.PlainDate.from("2021-01-01")), 2020, "previous year"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..10df67cf65 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.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. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.calendar.prototype.yearofweek +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.yearOfWeek({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.yearOfWeek({ ...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/Calendar/prototype/yearOfWeek/length.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/length.js new file mode 100644 index 0000000000..ef513c2254 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/length.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.calendar.prototype.yearofweek +description: Temporal.Calendar.prototype.yearOfWeek.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.Calendar.prototype.yearOfWeek, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.js new file mode 100644 index 0000000000..4bbf63865c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.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.calendar.prototype.yearofweek +description: Temporal.Calendar.prototype.yearOfWeek.name is "yearOfWeek". +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.Calendar.prototype.yearOfWeek, "name", { + value: "yearOfWeek", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.js new file mode 100644 index 0000000000..33016b31bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.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.calendar.prototype.yearofweek +description: > + Temporal.Calendar.prototype.yearOfWeek 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.Calendar.prototype.yearOfWeek(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.Calendar.prototype.yearOfWeek), false, + "isConstructor(Temporal.Calendar.prototype.yearOfWeek)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.js new file mode 100644 index 0000000000..ddffa0dd35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.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.calendar.prototype.yearofweek +description: The "yearOfWeek" property of Temporal.Calendar.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.Calendar.prototype.yearOfWeek, + "function", + "`typeof Calendar.prototype.yearOfWeek` is `function`" +); + +verifyProperty(Temporal.Calendar.prototype, "yearOfWeek", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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/Calendar/prototype/yearOfWeek/year-zero.js b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/year-zero.js new file mode 100644 index 0000000000..c6a42fb11e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/prototype/yearOfWeek/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.calendar.prototype.yearofweek +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.Calendar("iso8601"); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/shell.js b/js/src/tests/test262/built-ins/Temporal/Calendar/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/Calendar/subclass.js b/js/src/tests/test262/built-ins/Temporal/Calendar/subclass.js new file mode 100644 index 0000000000..cb13924cf3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/Calendar/subclass.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.calendar +description: Test for Temporal.Calendar subclassing. +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { +} + +const instance = new CustomCalendar("iso8601"); +assert.sameValue(instance.toString(), "iso8601"); +assert.sameValue(Object.getPrototypeOf(instance), CustomCalendar.prototype, "Instance of CustomCalendar"); +assert(instance instanceof CustomCalendar, "Instance of CustomCalendar"); +assert(instance instanceof Temporal.Calendar, "Instance of Temporal.Calendar"); + +reportCompare(0, 0); |