diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..d67a6248eb --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-datefromfields-called-with-null-prototype-fields.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-fields-undefined.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-fields-undefined.js new file mode 100644 index 0000000000..a9c1c7be3a --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-calendar-fields-undefined.js @@ -0,0 +1,27 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: > + When calendar.fields is undefined, yearOfWeek() doesn't perform an + observable array iteration to convert the property bag to PlainDate +features: [Temporal] +---*/ + +const calendar = new Temporal.Calendar("iso8601"); +calendar.fields = undefined; + +const instance = new Temporal.Calendar("iso8601"); + +// Detect observable array iteration: +const oldIterator = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function () { + throw new Test262Error(`array shouldn't be iterated: ${new Error().stack}`); +}; + +const arg = { year: 1981, month: 12, day: 15, calendar }; + +instance.yearOfWeek(arg); + +Array.prototype[Symbol.iterator] = oldIterator; diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js new file mode 100644 index 0000000000..762f4f4b7e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-leap-second.js @@ -0,0 +1,26 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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" +); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-number.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-number.js new file mode 100644 index 0000000000..fdb18c0552 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-number.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: A number is converted to a string, then to Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const arg = 19761118; + +const result = instance.yearOfWeek(arg); +assert.sameValue(result, 1976, "19761118 is a valid ISO string for PlainDate"); + +const numbers = [ + 1, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `Number ${arg} does not convert to a valid ISO string for PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-instance-does-not-get-calendar-property.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-instance-does-not-get-calendar-property.js new file mode 100644 index 0000000000..24d661a6ba --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-instance-does-not-get-calendar-property.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearofweek +description: > + A Temporal.Calendar instance passed to yearOfWeek() in a property bag does + not have its 'calendar' property observably checked +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = new Temporal.Calendar("iso8601"); +Object.defineProperty(calendar, "calendar", { + get() { + throw new Test262Error("calendar.calendar should not be accessed"); + }, +}); + +let arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +instance.yearOfWeek(arg); + +arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } }; +instance.yearOfWeek(arg); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..50d93686ee --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,28 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"; + +let arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result1 = instance.yearOfWeek(arg); +assert.sameValue( + result1, + 1976, + "leap second is a valid ISO string for calendar" +); + +arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } }; +const result2 = instance.yearOfWeek(arg); +assert.sameValue( + result2, + 1976, + "leap second is a valid ISO string for calendar (nested property)" +); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..f15d75d4c8 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-number.js @@ -0,0 +1,41 @@ +// Copyright (C) 2022 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 converted to a string, then to a calendar +features: [Temporal] +---*/ + +const instance = new Temporal.Calendar("iso8601"); + +const calendar = 19970327; + +let arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result1 = instance.yearOfWeek(arg); +assert.sameValue(result1, 1976, "19970327 is a valid ISO string for calendar"); + +arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } }; +const result2 = instance.yearOfWeek(arg); +assert.sameValue(result2, 1976, "19970327 is a valid ISO string for calendar (nested property)"); + +const numbers = [ + 1, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + let arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `Number ${calendar} does not convert to a valid ISO string for calendar` + ); + arg = { year: 1976, monthCode: "M11", day: 18, calendar: { calendar } }; + assert.throws( + RangeError, + () => instance.yearOfWeek(arg), + `Number ${calendar} does not convert to a valid ISO string for calendar (nested property)` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..bf85edd3ab --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-string.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}"`); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..e7094a99d7 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-wrong-type.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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 rangeErrorTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [calendar, description] of rangeErrorTests) { + let arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws(RangeError, () => instance.yearOfWeek(arg), `${description} does not convert to a valid ISO string`); + + arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar } }; + assert.throws(RangeError, () => instance.yearOfWeek(arg), `${description} does not convert to a valid ISO string (nested property)`); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], // TypeError due to missing dateFromFields() + [Temporal.Calendar, "Temporal.Calendar, object"], // ditto + [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields() +]; + +for (const [calendar, description] of typeErrorTests) { + let 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`); + + arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar } }; + assert.throws(TypeError, () => instance.yearOfWeek(arg), `${description} is not a valid property bag and does not convert to a string (nested property)`); +} + +const arg = { year: 2019, monthCode: "M11", day: 1, calendar: { calendar: undefined } }; +assert.throws(RangeError, () => instance.yearOfWeek(arg), `nested undefined calendar property is always a RangeError`); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-year-zero.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..3ea0af23ac --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-propertybag-calendar-year-zero.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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" + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..cefe90e1f5 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-calendar-annotation.js @@ -0,0 +1,31 @@ +// Copyright (C) 2022 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"], + ["2000-05-02T15:23[u-ca=iso8601][!u-ca=discord]", "second annotation ignored even with !"], +]; + +const instance = new Temporal.Calendar("iso8601"); + +tests.forEach(([arg, description]) => { + const result = instance.yearOfWeek(arg); + + assert.sameValue( + result, + 2000, + `calendar annotation (${description})` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-critical-unknown-annotation.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..41d6e9944e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-critical-unknown-annotation.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-invalid.js new file mode 100644 index 0000000000..63655935db --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.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` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-time-zone.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..13e9ab2efb --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-multiple-time-zone.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js new file mode 100644 index 0000000000..0157f0409e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-separators.js @@ -0,0 +1,26 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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})` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..f434d82009 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-time-zone-annotation.js @@ -0,0 +1,39 @@ +// Copyright (C) 2022 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 and no offset"], + ["2000-05-02[!Europe/Vienna]", "named, with !, no time, and no offset"], + ["2000-05-02[+00:00]", "numeric, with no time and no offset"], + ["2000-05-02[!-02:30]", "numeric, with !, no time, and no offset"], + ["2000-05-02+00:00[UTC]", "named, with offset and no time"], + ["2000-05-02+00:00[!Africa/Abidjan]", "named, with offset, !, and no time"], + ["2000-05-02+00:00[-08:00]", "numeric, with offset and no time"], + ["2000-05-02+00:00[!+01:00]", "numeric, with offset, !, 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})` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..eca37cb619 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-unknown-annotation.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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})` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..515475e969 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string-with-utc-designator.js @@ -0,0 +1,21 @@ +// Copyright (C) 2022 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" + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string.js new file mode 100644 index 0000000000..2d5f3c8b6c --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-string.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-wrong-type.js new file mode 100644 index 0000000000..1b9cb9fc98 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-wrong-type.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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 rangeErrorTests = [ + [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 rangeErrorTests) { + assert.throws(RangeError, () => 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`); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-convert.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..1f6a4f70ed --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-convert.js @@ -0,0 +1,19 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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)); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-slots.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..eee4172af7 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-slots.js @@ -0,0 +1,37 @@ +// Copyright (C) 2022 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, []); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..363f1fcd1c --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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)); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..61e5cb52c4 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,20 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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` + ); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..a8453dbd8e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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)); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..5a9e07dfcd --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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)); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.js new file mode 100644 index 0000000000..536a99eb37 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/basic.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.js new file mode 100644 index 0000000000..563fdef47e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/branding.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js new file mode 100644 index 0000000000..a9a38d3165 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/builtin.js @@ -0,0 +1,33 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..667ce85a5b --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,15 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-fields-iterable.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-fields-iterable.js new file mode 100644 index 0000000000..b1a82dbd04 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-fields-iterable.js @@ -0,0 +1,32 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-temporal-object.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-temporal-object.js new file mode 100644 index 0000000000..a906e9bd2c --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/calendar-temporal-object.js @@ -0,0 +1,26 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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 }); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js new file mode 100644 index 0000000000..499660dd52 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/cross-year.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..a5dd132338 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: 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"); + }); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/length.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/length.js new file mode 100644 index 0000000000..a50b2c2eeb --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/length.js @@ -0,0 +1,25 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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, +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.js new file mode 100644 index 0000000000..779bf5a496 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/name.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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, +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.js new file mode 100644 index 0000000000..133a3bd7af --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/not-a-constructor.js @@ -0,0 +1,21 @@ +// Copyright (C) 2022 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)"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.js new file mode 100644 index 0000000000..d0bb2aad44 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/prop-desc.js @@ -0,0 +1,21 @@ +// Copyright (C) 2022 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, +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/year-zero.js b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/year-zero.js new file mode 100644 index 0000000000..32cf9a9013 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearOfWeek/year-zero.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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" + ); +}); diff --git a/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/basic.js b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/basic.js new file mode 100644 index 0000000000..3da9ec3050 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/basic.js @@ -0,0 +1,26 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.yearofweek +description: Basic tests for yearOfWeek(). +features: [Temporal] +---*/ + +for (let i = 29; i <= 31; ++i) { + const plainDate = new Temporal.PlainDate(1975, 12, i); + assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`); +} +for (let i = 1; i <= 11; ++i) { + const plainDate = new Temporal.PlainDate(1976, 1, i); + assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`); +} +for (let i = 20; i <= 31; ++i) { + const plainDate = new Temporal.PlainDate(1976, 12, i); + assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`); +} +for (let i = 1; i <= 2; ++i) { + const plainDate = new Temporal.PlainDate(1977, 1, i); + assert.sameValue(plainDate.yearOfWeek, 1976, `${plainDate} should be in yearOfWeek 1976`); +} + diff --git a/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/branding.js b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/branding.js new file mode 100644 index 0000000000..236d9765dc --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/branding.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.yearofweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "yearOfWeek").get; + +assert.sameValue(typeof yearOfWeek, "function"); + +assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined"); +assert.throws(TypeError, () => yearOfWeek.call(null), "null"); +assert.throws(TypeError, () => yearOfWeek.call(true), "true"); +assert.throws(TypeError, () => yearOfWeek.call(""), "empty string"); +assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol"); +assert.throws(TypeError, () => yearOfWeek.call(1), "1"); +assert.throws(TypeError, () => yearOfWeek.call({}), "plain object"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDate), "Temporal.PlainDate"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDate.prototype), "Temporal.PlainDate.prototype"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/custom.js b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/custom.js new file mode 100644 index 0000000000..8543111858 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/custom.js @@ -0,0 +1,27 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.yearofweek +description: Custom calendar tests for yearOfWeek(). +includes: [compareArray.js] +features: [Temporal] +---*/ + +let calls = 0; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearOfWeek(...args) { + ++calls; + assert.compareArray(args, [pd], "yearOfWeek arguments"); + return 7; + } +} + +const calendar = new CustomCalendar(); +const pd = new Temporal.PlainDate(1830, 8, 25, calendar); +const result = pd.yearOfWeek; +assert.sameValue(result, 7, "result"); +assert.sameValue(calls, 1, "calls"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/prop-desc.js b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/prop-desc.js new file mode 100644 index 0000000000..27705984f9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/prop-desc.js @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindate.prototype.yearofweek +description: The "yearOfWeek" property of Temporal.PlainDate.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDate.prototype, "yearOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); diff --git a/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/validate-calendar-value.js b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/validate-calendar-value.js new file mode 100644 index 0000000000..0f1c3a0664 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/yearOfWeek/validate-calendar-value.js @@ -0,0 +1,51 @@ +// 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.plaindate.prototype.yearofweek +description: Validate result returned from calendar yearOfWeek() method +features: [Temporal] +---*/ + +const badResults = [ + [undefined, RangeError], + [Infinity, RangeError], + [-Infinity, RangeError], + [Symbol("foo"), TypeError], + [7n, TypeError], +]; + +badResults.forEach(([result, error]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.PlainDate(1981, 12, 15, calendar); + assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`); +}); + +const convertedResults = [ + [null, 0], + [true, 1], + [false, 0], + [7.1, 7], + [-7, -7], + [-0.1, 0], + [NaN, 0], + ["string", 0], + ["7", 7], + ["7.5", 7], + [{}, 0], + [{valueOf() { return 7; }}, 7], +]; + +convertedResults.forEach(([result, convertedResult]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.PlainDate(1981, 12, 15, calendar); + assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/basic.js new file mode 100644 index 0000000000..ec1a834b40 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/basic.js @@ -0,0 +1,12 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.yearofweek +description: Checking yearOfWeek for a "normal" case (non-undefined, non-boundary case, etc.) +features: [Temporal] +---*/ + +const calendar = Temporal.Calendar.from("iso8601"); +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar); +assert.sameValue(datetime.yearOfWeek, 1976, "check yearOfWeek information"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/branding.js b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/branding.js new file mode 100644 index 0000000000..3d779abef7 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/branding.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.yearofweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "yearOfWeek").get; + +assert.sameValue(typeof yearOfWeek, "function"); + +assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined"); +assert.throws(TypeError, () => yearOfWeek.call(null), "null"); +assert.throws(TypeError, () => yearOfWeek.call(true), "true"); +assert.throws(TypeError, () => yearOfWeek.call(""), "empty string"); +assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol"); +assert.throws(TypeError, () => yearOfWeek.call(1), "1"); +assert.throws(TypeError, () => yearOfWeek.call({}), "plain object"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDateTime), "Temporal.PlainDateTime"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.PlainDateTime.prototype), "Temporal.PlainDateTime.prototype"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/custom.js b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/custom.js new file mode 100644 index 0000000000..556ba8e5d5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/custom.js @@ -0,0 +1,27 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.yearofweek +description: Custom calendar tests for yearOfWeek(). +includes: [compareArray.js] +features: [Temporal] +---*/ + +let calls = 0; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearOfWeek(...args) { + ++calls; + assert.compareArray(args, [pdt], "yearOfWeek arguments"); + return 7; + } +} + +const calendar = new CustomCalendar(); +const pdt = new Temporal.PlainDateTime(1830, 8, 25, 20, 0, 0, 0, 0, 0, calendar); +const result = pdt.yearOfWeek; +assert.sameValue(result, 7, "result"); +assert.sameValue(calls, 1, "calls"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/prop-desc.js b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/prop-desc.js new file mode 100644 index 0000000000..11ef5f5f3d --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/prop-desc.js @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.yearofweek +description: The "yearOfWeek" property of Temporal.PlainDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainDateTime.prototype, "yearOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/validate-calendar-value.js b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/validate-calendar-value.js new file mode 100644 index 0000000000..af4f1debf8 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/yearOfWeek/validate-calendar-value.js @@ -0,0 +1,51 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaindatetime.prototype.yearofweek +description: Validate result returned from calendar yearOfWeek() method +features: [Temporal] +---*/ + +const badResults = [ + [undefined, RangeError], + [Infinity, RangeError], + [-Infinity, RangeError], + [Symbol("foo"), TypeError], + [7n, TypeError], +]; + +badResults.forEach(([result, error]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.PlainDateTime(1981, 12, 15, 14, 15, 45, 987, 654, 321, calendar); + assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`); +}); + +const convertedResults = [ + [null, 0], + [true, 1], + [false, 0], + [7.1, 7], + [-7, -7], + [-0.1, 0], + [NaN, 0], + ["string", 0], + ["7", 7], + ["7.5", 7], + [{}, 0], + [{valueOf() { return 7; }}, 7], +]; + +convertedResults.forEach(([result, convertedResult]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.PlainDateTime(1981, 12, 15, 14, 15, 45, 987, 654, 321, calendar); + assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`); +}); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/branding.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/branding.js new file mode 100644 index 0000000000..d154ed6117 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/branding.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.yearofweek +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const yearOfWeek = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "yearOfWeek").get; + +assert.sameValue(typeof yearOfWeek, "function"); + +assert.throws(TypeError, () => yearOfWeek.call(undefined), "undefined"); +assert.throws(TypeError, () => yearOfWeek.call(null), "null"); +assert.throws(TypeError, () => yearOfWeek.call(true), "true"); +assert.throws(TypeError, () => yearOfWeek.call(""), "empty string"); +assert.throws(TypeError, () => yearOfWeek.call(Symbol()), "symbol"); +assert.throws(TypeError, () => yearOfWeek.call(1), "1"); +assert.throws(TypeError, () => yearOfWeek.call({}), "plain object"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.ZonedDateTime), "Temporal.ZonedDateTime"); +assert.throws(TypeError, () => yearOfWeek.call(Temporal.ZonedDateTime.prototype), "Temporal.ZonedDateTime.prototype"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/custom.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/custom.js new file mode 100644 index 0000000000..936c59fb0d --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/custom.js @@ -0,0 +1,27 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.yearofweek +description: Custom calendar tests for yearOfWeek(). +includes: [compareArray.js] +features: [Temporal] +---*/ + +let calls = 0; +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + yearOfWeek(...args) { + ++calls; + assert.compareArray(args.map(String), [instance].map((arg) => arg.toPlainDateTime().toString()), "yearOfWeek arguments"); + return 7; + } +} + +const calendar = new CustomCalendar(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +const result = instance.yearOfWeek; +assert.sameValue(result, 7, "result"); +assert.sameValue(calls, 1, "calls"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/prop-desc.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/prop-desc.js new file mode 100644 index 0000000000..b5240a403e --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/prop-desc.js @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.yearofweek +description: The "yearOfWeek" property of Temporal.ZonedDateTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.ZonedDateTime.prototype, "yearOfWeek"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..d5b55c1d67 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,15 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.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 datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.yearOfWeek); +}); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..8b21af0260 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,19 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.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 datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => datetime.yearOfWeek, + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..df1ecffaf1 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,15 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.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 datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => datetime.yearOfWeek); +}); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..da5b81356d --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.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 datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => datetime.yearOfWeek); +}); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/validate-calendar-value.js b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/validate-calendar-value.js new file mode 100644 index 0000000000..8777551d4b --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/yearOfWeek/validate-calendar-value.js @@ -0,0 +1,51 @@ +// 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.zoneddatetime.prototype.yearofweek +description: Validate result returned from calendar yearOfWeek() method +features: [Temporal] +---*/ + +const badResults = [ + [undefined, RangeError], + [Infinity, RangeError], + [-Infinity, RangeError], + [Symbol("foo"), TypeError], + [7n, TypeError], +]; + +badResults.forEach(([result, error]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + assert.throws(error, () => instance.yearOfWeek, `${typeof result} not converted to integer`); +}); + +const convertedResults = [ + [null, 0], + [true, 1], + [false, 0], + [7.1, 7], + [-7, -7], + [-0.1, 0], + [NaN, 0], + ["string", 0], + ["7", 7], + ["7.5", 7], + [{}, 0], + [{valueOf() { return 7; }}, 7], +]; + +convertedResults.forEach(([result, convertedResult]) => { + const calendar = new class extends Temporal.Calendar { + yearOfWeek() { + return result; + } + }("iso8601"); + const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); + assert.sameValue(instance.yearOfWeek, convertedResult, `${typeof result} converted to integer ${convertedResult}`); +}); diff --git a/test/intl402/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js b/test/intl402/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..a30e76e74c --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/yearOfWeek/infinity-throws-rangeerror.js @@ -0,0 +1,21 @@ +// 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 eraYear 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("gregory"); +const base = { era: "ad", month: 5, day: 2, calendar: "gregory" }; + +[Infinity, -Infinity].forEach((inf) => { + assert.throws(RangeError, () => instance.yearOfWeek({ ...base, eraYear: inf }), `eraYear property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, "eraYear"); + assert.throws(RangeError, () => instance.yearOfWeek({ ...base, eraYear: obj })); + assert.compareArray(calls, ["get eraYear.valueOf", "call eraYear.valueOf"], "it fails after fetching the primitive value"); +});