From 715c196e44270cbaa3ac53d60a2f1a543498dd84 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Fri, 15 Apr 2022 09:12:54 +0200 Subject: [PATCH] Squashed commit of the following: commit 1c19242ae42d1f5e1de6ca43d6a7cb84e88ae964 Author: Shu-yu Guo Date: Wed Apr 13 14:06:45 2022 -0700 Remove check for per-iteration detach check in TypedArray.prototype.set Note that this test currently unintentionally passes, because a TypeError is thrown for failing to convert the undefined returned from the getter to a BigInt. But since this test was intended to test detaching, it's no longer valid and should still be removed. See https://github.com/tc39/test262/pull/3465#issuecomment-1098388916 commit 4dafd2158b5982730e49c6ed2abf55db0a4315ad Author: Ms2ger Date: Wed Apr 13 15:02:27 2022 +0200 Temporal: Remove some stray arguments to TemporalHelpers.assertDuration. commit c35ae2099d507365c3227d8c7a6084d4399b1692 Author: Ms2ger Date: Wed Apr 13 18:31:57 2022 +0200 Temporal: Some more tests for PlainDateTime#with. (#3481) commit d9616ed91f1b76a1c2bea0c15efb89a9053faef0 Author: Philip Chimento Date: Fri Apr 8 16:30:39 2022 -0700 Add tests for direction of rounding functionality The round() and toString() methods of Temporal.Instant, PlainDateTime, and ZonedDateTime can round up or down. However, the instance must not be treated as "negative" even when the time is before 1 BCE (years are negative) or before the Unix epoch (epoch nanoseconds are negative). That is, rounding down is always towards the Big Bang, and rounding up is always away from it. Add tests that verify this. commit 3905c0c80afb5d6cf0c433fa9232d63f42ef6141 Author: Philip Chimento Date: Fri Apr 8 11:39:40 2022 -0700 Expand toString() rounding tests from PlainTime to cover other types This takes the tests of the rounding functionality of Temporal.PlainTime.p.toString() and adds similar tests covering the equivalent functionality to Duration, Instant, PlainDateTime, and ZonedDateTime: all the types that have rounding and precision controls for how they output their subsecond values. It also takes the opportunity to improve the existing PlainTime tests: - fractionalseconddigits-auto.js: More descriptive variable names. Added assertion messages. - fractionalseconddigits-number.js: Ditto. - rounding-cross-midnight.js: Use constructor directly to remove coupling with from(). - roundingmode-*.js: Add additional tests for specifying the precision using fractionalSecondDigits. - smallestunit-fractionalseconddigits.js: Add assertion messages. commit 4ac16c25896be91c8b73659be621488ca2d36074 Author: Philip Chimento Date: Fri Apr 8 10:52:39 2022 -0700 Add tests for Temporal options bags being of the wrong type This consolidates the few existing tests for options bags in Temporal being of the wrong type, and adds them for every entry point in Temporal that accepts an options bag. These are mostly identical tests, but there is a variation for methods like round() where either an options bag or string is accepted. commit 9f303112bd89f5f9dc29b46deeb305d5b8285133 Author: Philip Chimento Date: Thu Apr 7 18:32:15 2022 -0700 Repeat Instant.p.toString() test with timeZone parameter for IANA time zones This adds to the intl402/ tree a copy of built-ins/Temporal/Instant/prototype/toString/timezone-offset.js but which uses IANA time zones. commit 9b2c98c02b2de615195fe3f622072124d23d60d9 Author: Philip Chimento Date: Thu Apr 7 18:27:47 2022 -0700 Bring existing "invalid string" tests for smallestUnit and largestUnit in sync Add a consistent set of invalid strings for all of the smallestunit-invalid-string.js and largestunit-invalid-string.js tests: - "era" and "eraYear" in singular and plural - all of the units that are disallowed for that particular method call, in singular and plural - an allowed unit with \0 at the end - an allowed unit with an "i" replaced by a dotless i - an allowed unit but with all-caps - an unrelated string. commit b4c0aeda2023fa178a46af0b49dd4a501153820b Author: Philip Chimento Date: Thu Apr 7 16:54:51 2022 -0700 Bring existing toString options tests in sync with each other Of the toString() methods that have options for printing a time with seconds and fractional seconds, PlainTime seems to have the most comprehensive set of tests. Bring all the others (Duration, Instant, PlainDateTime, and ZonedDateTime) in sync with PlainTime, and edit the PlainTime ones where necessary to include improvements from the others. Tests: - fractionalseconddigits-invalid-string.js: copy and expand on PlainTime's more comprehensive set of invalid strings. Add assertion message. Fix front matter. - fractionalseconddigits-non-integer.js: Fix front matter. - fractionalseconddigits-out-of-range.js: make sure infinity is tested. Add assertion messages. Fix front matter. - fractionalseconddigits-undefined.js: copy PlainTime's more comprehensive test with whole minutes, whole seconds, and subseconds. Copy PlainTime's test of an empty function object. Add more descriptive variable names and assertion messages. Fix front matter. - fractionalseconddigits-wrong-type.js: inline and delete TemporalHelper used here; it was only good for this test anyway. Improve assertion messages. - smallestunit-valid-units.js: copy PlainTime's test with a second value with zero seconds even. Refactor repetitive tests into a loop. Copy the invalid unit "era" from the Instant test. Add assertion messages. commit 2c880bf5c1d98b3a5dd59a18c5e37aa03ea3f43a Author: Ms2ger Date: Tue Apr 12 11:34:57 2022 +0200 Temporal: Some more tests for PlainDateTime.compare. commit a226601d12dac85fb779f7396d6bc28aa3038963 Author: Ms2ger Date: Tue Apr 12 17:32:18 2022 +0200 Temporal: Some more tests for PlainDateTime#withPlainDate. commit 7823be3e9627706e9a6ac73774ed304dd0e2289a Author: Ms2ger Date: Tue Apr 12 17:21:24 2022 +0200 Temporal: Move test with typo in name. commit 62e0130447d1fa08586252dbbcc103b6f713a31e Author: Ms2ger Date: Tue Apr 12 19:02:53 2022 +0200 Temporal: Some more tests for PlainDateTime#equals. (#3479) commit 5f1aba63ee799829fad0b94ff49b17e3314f2835 Author: Jesse Alama Date: Tue Apr 12 17:36:03 2022 +0200 Temporal: Port Demitasse PlainDateTime `round` tests (#3478) Co-authored-by: Ms2ger commit 9055521fc7ea8d44a34fd4fe137f2c25c60655ee Author: rwaldron Date: Mon Apr 11 13:08:37 2022 -0400 ShadowRealm: fix for incorrect test commit d4ede37b6757eefa91ede2f344568f77962e1255 Author: Mike Pennisi Date: Fri Apr 8 20:37:17 2022 -0400 Add assertions for functions with infinite length A prior version of ECMA262 described invalid mathematical operations with infinite values [1]. Update the test metadata to reflect the corrected specification text, and add two assertions for the obsolete conditions. [1] ".bind on a function with infinite length has imprecise spec and engine divergences" https://github.com/tc39/ecma262/issues/2170 commit 24e4eb09dae17e0a17eadb8b7dbf2cf363c7596e Author: rwaldron Date: Mon Apr 11 10:16:36 2022 -0400 ShadowRealm: add more tests for globalThis ordinary object conformance commit d7c0a2076c2b0c1531aef7069d4abe70eec44ee3 Author: Shu-yu Guo Date: Mon Apr 4 16:36:56 2022 -0700 Remove check for per-comparator call detach check in TypedArray.prototype.sort This updates tests in line with the normative change in https://github.com/tc39/ecma262/pull/2723 commit 3ac6b7336987d329a750c5093beb8f55d5bbad12 Author: Shu-yu Guo Date: Mon Apr 4 16:42:58 2022 -0700 Add test that TypedArray.prototype.set doesn't throw if a getter for an element detaches commit 8b29141224f42ac13f247cfd553aeda798bd49e0 Author: Shu-yu Guo Date: Mon Apr 4 15:44:22 2022 -0700 Remove check for per-iteration detach check in TypedArray.prototype.set This updates tests in line with the normative change in https://github.com/tc39/ecma262/pull/2646 commit f60d7cf67d98996f750c8acee4b2f28600bf3ddb Author: rwaldron Date: Tue Apr 5 11:18:45 2022 -0400 fixup! Fix false negative in for-in test commit 384a4e1368523ce959c8b7c376036a734decd6ca Author: rwaldron Date: Tue Apr 5 11:18:10 2022 -0400 Fix false negative in for-in test As originally written, this test would spuriously pass when the deleted property was incorrectly visited by enumation but correctly removed from the object. In such cases, the accumulator string would take the form "aa1baundefinedca3" And satisfy all conditions intended to highlight implementation errors. Refactor the test to avoid false negative by using an object with a null prototype and verifying the exact contents of the accumulator string. commit 3c88e9b6193b124e7cc993867f05cf0f25e049d2 Author: Mike Pennisi Date: Fri Apr 1 18:16:06 2022 -0400 Fix false negative in for-in test As originally written, this test would spuriously pass when the deleted property was incorrectly visited by enumation but correctly removed from the object. In such cases, the accumulator string would take the form "aa1baundefinedca3" And satisfy all conditions intended to highlight implementation errors. Refactor the test to avoid false negative by using an object with a null prototype and verifying the exact contents of the accumulator string. commit 833a784f205c1dfe2c12af4e9f8753b9ab4f606e Author: Philip Chimento Date: Thu Mar 31 18:16:17 2022 -0700 Tests for computing PlainYearMonth addition and subtraction in correct calendar space https://github.com/tc39/proposal-temporal/pull/2003 is a normative change that reached consensus at the March 2022 TC39 plenary meeting. This adds tests that verify the new spec text is implemented correctly, performing arithmetic on a PlainYearMonth instance that would previously have thrown an error if it was implemented as written. commit c58ac691ebb16ce23af564d64c1f8c0a63479afa Author: Richard Gibson Date: Fri Mar 25 08:35:50 2022 -0400 Test that "infinity" is not recognized as numeric commit c572588ea91e040a7fc9b639ae74a90810644892 Author: Richard Gibson Date: Thu Mar 24 16:52:05 2022 -0400 Test that "INFINITY" is not recognized as numeric Fixes #3442 commit 51822ff2d8aa0687c76a0fef85f288f34156c4fa Author: Shu-yu Guo Date: Thu Mar 31 16:37:06 2022 -0700 Update Symbol.species tests for TypedArray constructor This updates tests in line with https://github.com/tc39/ecma262/pull/2719 commit da507a703e2bdc22b89956ebe6dff35959f34b16 Author: Philip Chimento Date: Thu Mar 31 12:36:06 2022 -0700 Tests for Temporal formatting the year appropriately as 4 or 6 digits https://github.com/tc39/proposal-temporal/pull/2090 is a normative change that reached consensus at the March 2022 TC39 plenary meeting. This adds tests that verify the change made to the formatting of years between 0 and 999 inclusive in all toString and toJSON methods of Temporal types that can output an ISO year number in their return value. commit cdcf2a3f091a56fa6674877336ed537671e639bb Author: Frank Tang Date: Mon Jul 19 11:50:58 2021 -0700 Add tests for Temporal.Calendar.p*.inLeapYear (Philip, March 2022: This was originally Frank's PR #3056. I did some reformatting, removed duplicate tests, and combined with some existing tests.) commit 16aefcc6cf851094aa55fc612876dbad04c62c2c Author: Frank Tang Date: Mon Jul 19 12:08:18 2021 -0700 Add tests for Temporal.Calendar.p*.mergeFields (Philip, March 2022: This was originally Frank's PR #3057. I did some reformatting, removed duplicate tests, addressed the review comments that I left the first time around, and added some cases that I felt were not yet complete.) commit 6bae30c1b27e5510fae54e44091f1827865c9862 Author: Frank Tang Date: Mon Jul 19 13:31:55 2021 -0700 Add tests for Temporal.Calendar.p*.monthDayFromFields (Philip, March 2022: This was originally Frank's PR #3058. I did some reformatting, removed duplicate tests, and combined with some existing tests.) commit c22b8ab9c42ef327f371be3c9e6d7c4905f5e4be Author: Frank Tang Date: Mon Jul 19 13:45:21 2021 -0700 Add tests for Temporal.Calendar.p*.monthsInYear (Philip, March 2022: This was originally Frank's PR #3059. I did some reformatting, removed duplicate tests, and combined with some existing tests.) commit b064eb64f35f9b36cc490caa6c2bd0f0781ef6d6 Author: Frank Tang Date: Mon Jul 19 14:00:42 2021 -0700 Add tests for Temporal.Calendar.p*.weekOfYear (Philip, March 2022: This was originally Frank's PR #3060. I did some reformatting, removed a test that didn't exercise the whole feature, and combined some duplicate tests with some existing tests.) commit ac19506a01099c1931a8dfdc76d538078ea33e19 Author: Philip Chimento Date: Tue Feb 1 15:38:24 2022 -0800 Add tests ensuring that observable calls are made with options === undefined Where possible, observable calls originating from within Temporal, that require an options argument, should pass `undefined` as that options argument, rather than `{}` or `Object.create(null)`. See tc39/proposal-temporal#1685. commit 16ad841e7e5d5ca80fc03e73c3b273e029428608 Author: Philip Chimento Date: Wed Feb 2 16:42:53 2022 -0800 Fix arithmetic in TemporalHelpers.oneShiftTimeZone I made a mistake with one of the signs in one of the time zones that we use for verifying DST handling. Luckily this didn't affect any previously existing tests, but it affected some new tests that I'm going to add in the next commit. How do I know that _this_ arithmetic is correct? I feel reasonably confident with the added test. commit 276e79d62e8c45bc1e427fc680320c4899eace27 Author: Mike Pennisi Date: Fri Mar 25 19:47:14 2022 -0400 Deprecate some property helpers Document the preference for `verifyProperty` over the various other property-related helper functions. commit 5eb7dfbced484d99da4e80e63f36b8d5a0c051f8 Author: jugglinmike Date: Mon Apr 4 11:27:22 2022 -0400 Remove configuration file for third-party tool (#3450) The `.jshintrc` file configures the JavaScript "linting" tool named JSHint. Test262 does not depend on that tool, making the file's purpose and validity ambiguous and potentially distracting. commit 926b0960d737b9f1dfd0ec0c1dfd95d836016d33 Author: Romulo Cintra Date: Thu Mar 31 23:53:20 2022 +0200 update nfv3 test for roundingIncrement (#3441) commit 4c7c24646a395085a4a1bd006d686f6b52e1b517 Author: Jesse Alama Date: Wed Mar 30 17:33:52 2022 +0200 Check a variety of offset Etc/GMT timezones (#3403) Tests for normative change https://github.com/tc39/proposal-temporal/pull/2050 commit fe40aea50c23fbccb7bb4bef23f64af3a3239715 Author: Jesse Alama Date: Mon Feb 21 14:14:44 2022 +0100 Emit fallback day 1 commit 9aaa22cb06cedecf5395c5b644c102f554d3f15d Author: Jesse Alama Date: Mon Feb 21 14:06:52 2022 +0100 Ensure fallback years values are present commit ee1f96235b8fffb25141b812f3cee4f8863d4553 Author: Jesse Alama Date: Fri Feb 4 08:50:10 2022 +0100 Ensure reference data is emitted when calendarName = 'always' References: + https://github.com/tc39/proposal-temporal/issues/1971 commit 76b0bafba67dcfda8e4eafc5c3b9ea72efa78833 Author: Jesse Alama Date: Fri Feb 11 09:21:10 2022 +0100 Update test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js Co-authored-by: Philip Chimento commit 2aa754b7cf1c83999370a6a800fe261448315e9d Author: Jesse Alama Date: Thu Feb 3 11:54:45 2022 +0100 Add test for DST balancing References: + https://github.com/tc39/proposal-temporal/issues/1791 Thanks @ptomato for the suggestion to use `springForwardFallBackTimeZone`. commit 3ab8adc237a026f7e249ee5e64e6b654e7fcfc08 Author: Richard Gibson Date: Wed Mar 23 00:17:23 2022 -0400 Require String.prototype.localeCompare to check for canonical equivalence commit 3eea1a7959696aef42f935baf7ab54f4840b59f4 Author: Philip Chimento Date: Thu Mar 24 16:37:19 2022 -0700 Add tests for various invalid ISO strings for PlainDate These tests check API entry points that convert strings to Temporal.PlainDate, with a list of various strings that are all not valid for that context according to ISO 8601. commit ad74a4ebbaac5bd6e96a9e990d6ce90da70594ca Author: Philip Chimento Date: Thu Mar 24 16:32:06 2022 -0700 Rename some "argument-string" tests to be more specific I'd like to add basic functionality tests for string arguments, and these tests are testing something more specific: that a Get of the "overflow" property on the passed-in options object is observable. Rename accordingly. commit 52af2b67638ae36395e39b665ba13f02f10225d3 Author: Frank Tang Date: Mon Jul 19 14:26:11 2021 -0700 Add tests for Temporal.Calendar.p*.yearMonthFromFields (Philip, March 2022: This was originally Frank's PR #3061. I did some reformatting, removed duplicate tests, and combined with some existing tests.) commit 0bad719e79f44e9c7d846c0c5941cd5a50c8c193 Author: Frank Tang Date: Mon Jul 19 14:50:02 2021 -0700 Add test for Temporal.Duration.p*.abs (Philip, March 2022: This was originally Frank's PR #3062. I did some reformatting and removed duplicate tests) commit f23602f6cef979d807423e1e09df819c8a22a51a Author: Frank Tang Date: Mon Jul 19 14:59:43 2021 -0700 Add test for Temporal.Duration.p*.negated (Philip, March 2022: This was originally Frank's PR #3063. I did some reformatting and removed duplicate tests) commit b8af7ff3698ffe4d6b21d21687a8063fd50ae891 Author: Frank Tang Date: Mon Jul 19 15:10:08 2021 -0700 Add test for Temporal.Duration.p*.toJSON (Philip, March 2022: This was originally Frank's PR #3064. I did some reformatting and removed duplicate tests) commit 2c8b69f8d09d807200267dfc1d2db91f6457c6e1 Author: Frank Tang Date: Mon Jul 19 15:32:37 2021 -0700 Add tests for Temporal.Duration.p*.with (Philip, March 2022: This was originally Frank's PR #3065. I did some reformatting, removed duplicate tests, and combined with some existing tests.) commit f59bafaa20445100fbf6fc43df133c33613190e1 Author: Iban Eguia Moraza Date: Mon Mar 28 21:22:05 2022 +0200 Fixed YAML in some new test metadata commit 99b2a70789b27d433f9036b98572a4443d91e01f Author: Jesse Alama Date: Sat Mar 26 01:13:17 2022 +0100 Use ECMAScript version 11 (#3448) We use BigInt syntax in a bunch of tests. This change registers that fact with linters that use `.jshintrc`. commit f964584508f44d0d56bcd9a54cf77afac035e815 Author: Ms2ger Date: Fri Mar 25 13:25:54 2022 +0100 Expand overflow-invalid-string.js tests. --- .jshintrc | 4 - harness/propertyHelper.js | 35 ++- harness/temporalHelpers.js | 75 +++--- .../v8/mjsunit/harmony/to-number.js | 2 + .../bind/instance-length-tointeger.js | 21 +- test/built-ins/Number/S15.7.1.1_A1.js | 2 + .../throws-typeerror-on-revoked-proxy.js | 2 +- ...bject.js => globalthis-ordinary-object.js} | 24 ++ .../throws-typeerror-wrap-throwing.js | 2 +- .../prototype/localeCompare/15.5.4.9_CE.js | 42 ++- .../dateAdd/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/dateAdd/options-wrong-type.js | 23 ++ .../dateAdd/overflow-invalid-string.js | 11 +- .../dateFromFields/options-wrong-type.js | 23 ++ .../dateFromFields/overflow-invalid-string.js | 12 +- .../dateUntil/argument-string-invalid.js | 67 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/dateUntil/options-wrong-type.js | 23 ++ .../prototype/day/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../dayOfWeek/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../dayOfYear/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../daysInMonth/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../daysInWeek/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../daysInYear/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../inLeapYear/argument-string-invalid.js | 61 +++++ .../prototype/inLeapYear/argument-string.js | 26 ++ .../Calendar/prototype/inLeapYear/basic.js | 17 +- .../Calendar/prototype/inLeapYear/branding.js | 20 +- ...romfields-called-with-options-undefined.js | 15 ++ .../Calendar/prototype/mergeFields/basic.js | 33 +++ .../iso8601-calendar-month-monthCode.js | 99 ++++++++ .../mergeFields/non-string-properties.js | 34 +++ .../month/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../monthCode/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/monthDayFromFields/basic.js | 40 +++ .../fields-missing-properties.js | 24 ++ .../monthDayFromFields/fields-not-object.js | 2 +- .../monthDayFromFields/monthcode-invalid.js | 31 +++ .../monthDayFromFields/options-wrong-type.js | 23 ++ .../monthDayFromFields/overflow-constrain.js | 91 +++++++ .../overflow-invalid-string.js | 9 +- .../monthDayFromFields/overflow-reject.js | 64 +++++ .../monthDayFromFields/reference-year-1972.js | 23 ++ .../monthsInYear/argument-string-invalid.js | 61 +++++ .../prototype/monthsInYear/argument-string.js | 18 ++ .../Calendar/prototype/monthsInYear/basic.js | 6 +- .../prototype/monthsInYear/branding.js | 20 +- ...romfields-called-with-options-undefined.js | 15 ++ .../weekOfYear/argument-plaindate.js | 76 ++++++ .../weekOfYear/argument-plaindatetime.js | 76 ++++++ .../weekOfYear/argument-string-invalid.js | 61 +++++ .../prototype/weekOfYear/argument-string.js | 39 +++ .../Calendar/prototype/weekOfYear/branding.js | 20 +- ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/year/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/yearMonthFromFields/basic.js | 40 +++ .../prototype/yearMonthFromFields/branding.js | 20 +- .../fields-missing-properties.js | 22 ++ .../yearMonthFromFields/fields-not-object.js | 2 +- .../yearMonthFromFields/monthcode-invalid.js | 31 +++ .../yearMonthFromFields/options-not-object.js | 17 ++ .../yearMonthFromFields/options-wrong-type.js | 23 ++ .../yearMonthFromFields/overflow-constrain.js | 91 +++++++ .../overflow-invalid-string.js | 9 +- .../yearMonthFromFields/overflow-reject.js | 26 ++ ...r-dateadd-called-with-options-undefined.js | 22 ++ .../Duration/compare/options-wrong-type.js | 22 ++ .../Duration/compare/twenty-five-hour-day.js | 33 +++ .../Temporal/Duration/prototype/abs/basic.js | 39 +++ .../prototype/add/options-wrong-type.js | 23 ++ .../Duration/prototype/negated/basic.js | 51 ++++ ...r-dateadd-called-with-options-undefined.js | 73 ++++++ .../prototype/round/options-wrong-type.js | 24 ++ .../round/smallestunit-invalid-string.js | 18 +- .../prototype/subtract/options-wrong-type.js | 23 ++ .../Duration/prototype/toJSON/basic.js | 240 ++++++++++++++++++ .../toString/fractionalseconddigits-auto.js | 21 ++ .../fractionalseconddigits-invalid-string.js | 5 +- .../toString/fractionalseconddigits-number.js | 28 ++ .../fractionalseconddigits-out-of-range.js | 12 +- .../fractionalseconddigits-undefined.js | 21 +- .../fractionalseconddigits-wrong-type.js | 24 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../prototype/toString/roundingmode-ceil.js | 34 +++ .../prototype/toString/roundingmode-floor.js | 34 +++ .../toString/roundingmode-halfExpand.js | 34 +++ .../prototype/toString/roundingmode-trunc.js | 34 +++ .../smallestunit-fractionalseconddigits.js | 29 +++ .../toString/smallestunit-invalid-string.js | 31 ++- .../toString/smallestunit-valid-units.js | 36 ++- ...r-dateadd-called-with-options-undefined.js | 49 ++++ .../prototype/total/options-wrong-type.js | 15 +- .../Duration/prototype/with/all-negative.js | 93 +++++++ .../Duration/prototype/with/all-positive.js | 92 +++++++ .../with/argument-object-wrong-shape.js | 31 +++ .../prototype/with/argument-wrong-type.js | 27 ++ .../Duration/prototype/with/branding.js | 20 +- .../prototype/with/partial-positive.js | 86 +++++++ .../with/sign-conflict-throws-rangeerror.js | 28 ++ .../prototype/round/options-wrong-type.js | 17 +- .../prototype/round/rounding-direction.js | 30 +++ .../round/smallestunit-invalid-string.js | 26 +- .../since/largestunit-invalid-string.js | 27 +- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 27 +- .../Instant/prototype/toJSON/year-format.js | 53 ++++ .../toString/fractionalseconddigits-auto.js | 23 ++ .../fractionalseconddigits-invalid-string.js | 7 +- .../fractionalseconddigits-non-integer.js | 2 +- .../toString/fractionalseconddigits-number.js | 33 +++ .../fractionalseconddigits-out-of-range.js | 14 +- .../fractionalseconddigits-undefined.js | 27 +- .../fractionalseconddigits-wrong-type.js | 24 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../toString/rounding-cross-midnight.js | 13 + .../prototype/toString/rounding-direction.js | 30 +++ .../prototype/toString/roundingmode-ceil.js | 37 +++ .../prototype/toString/roundingmode-floor.js | 37 +++ .../toString/roundingmode-halfExpand.js | 37 +++ .../prototype/toString/roundingmode-trunc.js | 37 +++ .../smallestunit-fractionalseconddigits.js | 30 +++ .../toString/smallestunit-invalid-string.js | 28 +- .../toString/smallestunit-valid-units.js | 38 ++- .../Instant/prototype/toString/year-format.js | 53 ++++ .../until/largestunit-invalid-string.js | 27 +- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 27 +- .../compare/argument-string-invalid.js | 66 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../PlainDate/from/argument-string-invalid.js | 76 ++++-- ...le-get-overflow-argument-string-invalid.js | 30 +++ ...bservable-get-overflow-argument-string.js} | 0 .../PlainDate/from/options-wrong-type.js | 22 ++ .../PlainDate/from/overflow-invalid-string.js | 16 +- .../prototype/add/options-wrong-type.js | 23 ++ .../prototype/add/overflow-invalid-string.js | 10 +- .../equals/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ .../since/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ .../prototype/since/largestunit-default.js | 14 +- .../since/largestunit-higher-units.js | 4 +- .../since/largestunit-invalid-string.js | 29 ++- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 29 ++- .../prototype/subtract/options-wrong-type.js | 23 ++ .../subtract/overflow-invalid-string.js | 10 +- .../PlainDate/prototype/toJSON/year-format.js | 47 ++++ ...romfields-called-with-options-undefined.js | 16 ++ ...romfields-called-with-options-undefined.js | 16 ++ .../prototype/toString/options-wrong-type.js | 23 ++ .../prototype/toString/year-format.js | 47 ++++ .../until/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ .../prototype/until/largestunit-default.js | 14 +- .../until/largestunit-higher-units.js | 2 +- .../until/largestunit-invalid-string.js | 29 ++- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 29 ++- .../prototype/with/options-wrong-type.js | 23 ++ .../prototype/with/overflow-invalid-string.js | 12 +- .../Temporal/PlainDateTime/compare/basic.js | 25 +- .../PlainDateTime/compare/calendar-ignored.js | 19 ++ .../PlainDateTime/from/options-wrong-type.js | 22 ++ .../from/overflow-invalid-string.js | 14 +- .../prototype/add/options-wrong-type.js | 23 ++ .../prototype/add/overflow-invalid-string.js | 7 +- .../PlainDateTime/prototype/equals/basic.js | 6 + .../prototype/equals/calendar-checked.js | 36 +++ .../PlainDateTime/prototype/round/balance.js | 19 ++ .../prototype/round/options-wrong-type.js | 24 ++ .../prototype/round/rounding-direction.js | 31 +++ .../round/roundingincrement-divides.js | 53 ++++ .../roundingincrement-does-not-divide.js | 18 ++ .../round/roundingincrement-one-day.js | 17 ++ .../prototype/round/roundingmode-basic.js | 47 ++++ .../round/roundingmode-ceil-basic.js | 30 +++ .../round/roundingmode-floor-basic.js | 29 +++ .../round/roundingmode-halfexpand-basic.js | 30 +++ .../roundingmode-halfexpand-is-default.js | 31 +++ .../round/roundingmode-trunc-basic.js | 29 +++ .../round/smallestunit-invalid-string.js | 24 +- ...hrows-argument-object-insufficient-data.js | 16 ++ .../prototype/round/throws-argument-object.js | 16 ++ .../prototype/round/throws-no-argument.js | 16 ++ .../prototype/round/throws-undefined.js | 16 ++ .../since/largestunit-invalid-string.js | 19 +- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 19 +- .../prototype/subtract/options-wrong-type.js | 23 ++ .../subtract/overflow-invalid-string.js | 9 +- .../prototype/toJSON/year-format.js | 47 ++++ ...romfields-called-with-options-undefined.js | 16 ++ ...romfields-called-with-options-undefined.js | 16 ++ .../toString/fractionalseconddigits-auto.js | 23 ++ .../fractionalseconddigits-invalid-string.js | 7 +- .../fractionalseconddigits-non-integer.js | 2 +- .../toString/fractionalseconddigits-number.js | 33 +++ .../fractionalseconddigits-out-of-range.js | 12 +- .../fractionalseconddigits-undefined.js | 26 +- .../fractionalseconddigits-wrong-type.js | 24 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../toString/rounding-cross-midnight.js | 13 + .../prototype/toString/rounding-direction.js | 30 +++ .../prototype/toString/roundingmode-ceil.js | 37 +++ .../prototype/toString/roundingmode-floor.js | 37 +++ .../toString/roundingmode-halfExpand.js | 37 +++ .../prototype/toString/roundingmode-trunc.js | 37 +++ .../smallestunit-fractionalseconddigits.js | 30 +++ .../toString/smallestunit-invalid-string.js | 28 +- .../toString/smallestunit-valid-units.js | 41 ++- .../prototype/toString/year-format.js | 47 ++++ .../toZonedDateTime/options-wrong-type.js | 23 ++ .../until/largestunit-invalid-string.js | 19 +- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 19 +- .../prototype/until/units-changed.js | 66 +++++ .../prototype/with/argument-not-object.js | 22 ++ .../prototype/with/calendar-options.js | 27 ++ .../with/calendar-temporal-object-throws.js | 33 +++ .../prototype/with/options-wrong-type.js | 23 ++ .../prototype/with/order-of-operations.js | 14 +- .../prototype/with/overflow-invalid-string.js | 10 +- ...s => argument-object-insufficient-data.js} | 0 .../argument-plaindate-calendar-noniso.js | 38 +++ .../argument-plaindate-calendar-same-id.js | 40 +++ ...argument-plaindate-calendar-same-object.js | 42 +++ .../argument-plaindate-calendar.js | 38 +++ .../withPlainDate/argument-string-invalid.js | 61 +++++ .../argument-string-iso-calendar.js | 2 +- ...romfields-called-with-options-undefined.js | 16 ++ .../Temporal/PlainMonthDay/calendar-always.js | 24 ++ ...romfields-called-with-options-undefined.js | 23 ++ .../PlainMonthDay/from/options-wrong-type.js | 22 ++ .../from/overflow-invalid-string.js | 14 +- ...romfields-called-with-options-undefined.js | 33 +++ .../prototype/toJSON/year-format.js | 55 ++++ .../prototype/toString/calendarname-always.js | 4 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../prototype/toString/year-format.js | 55 ++++ .../prototype/with/options-wrong-type.js | 23 ++ .../prototype/with/overflow-invalid-string.js | 10 +- ...e-get-overflow-argument-string-invalid.js} | 0 .../PlainTime/from/options-wrong-type.js | 22 ++ .../PlainTime/from/overflow-invalid-string.js | 16 +- .../prototype/round/options-wrong-type.js | 24 ++ .../round/smallestunit-invalid-string.js | 27 +- .../since/largestunit-invalid-string.js | 27 +- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 27 +- .../argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ .../toString/fractionalseconddigits-auto.js | 16 +- .../fractionalseconddigits-invalid-string.js | 7 +- .../fractionalseconddigits-non-integer.js | 2 +- .../toString/fractionalseconddigits-number.js | 37 ++- .../fractionalseconddigits-out-of-range.js | 14 +- .../fractionalseconddigits-undefined.js | 24 +- .../fractionalseconddigits-wrong-type.js | 24 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../toString/rounding-cross-midnight.js | 2 +- .../prototype/toString/roundingmode-ceil.js | 28 +- .../prototype/toString/roundingmode-floor.js | 28 +- .../toString/roundingmode-halfExpand.js | 28 +- .../prototype/toString/roundingmode-trunc.js | 28 +- .../smallestunit-fractionalseconddigits.js | 5 +- .../toString/smallestunit-invalid-string.js | 28 +- .../toString/smallestunit-valid-units.js | 47 +++- .../argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ .../until/largestunit-invalid-string.js | 27 +- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 27 +- .../prototype/with/options-wrong-type.js | 23 ++ .../prototype/with/overflow-invalid-string.js | 10 +- .../PlainYearMonth/calendar-always.js | 24 ++ ...romfields-called-with-options-undefined.js | 32 +++ ...romfields-called-with-options-undefined.js | 23 ++ .../PlainYearMonth/from/options-wrong-type.js | 22 ++ .../from/overflow-invalid-string.js | 16 +- .../add/calendar-datefromfields-called.js | 147 +++++++++++ .../prototype/add/options-wrong-type.js | 23 ++ .../prototype/add/overflow-invalid-string.js | 10 +- ...romfields-called-with-options-undefined.js | 35 +++ ...romfields-called-with-options-undefined.js | 16 ++ ...romfields-called-with-options-undefined.js | 35 +++ .../since/largestunit-invalid-string.js | 33 ++- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 33 ++- .../calendar-datefromfields-called.js | 147 +++++++++++ .../prototype/subtract/options-wrong-type.js | 23 ++ .../subtract/overflow-invalid-string.js | 10 +- .../prototype/toJSON/year-format.js | 47 ++++ .../prototype/toString/calendarname-always.js | 2 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../prototype/toString/year-format.js | 47 ++++ ...romfields-called-with-options-undefined.js | 16 ++ ...romfields-called-with-options-undefined.js | 35 +++ .../until/largestunit-invalid-string.js | 33 ++- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 33 ++- .../prototype/with/options-wrong-type.js | 11 +- .../prototype/with/overflow-invalid-string.js | 10 +- .../getInstantFor/options-wrong-type.js | 23 ++ .../ZonedDateTime/from/options-wrong-type.js | 22 ++ .../from/overflow-invalid-string.js | 14 +- .../prototype/add/options-wrong-type.js | 23 ++ .../prototype/add/overflow-invalid-string.js | 9 +- .../prototype/round/options-wrong-type.js | 24 ++ .../prototype/round/rounding-direction.js | 30 +++ .../round/smallestunit-invalid-string.js | 24 +- ...r-dateadd-called-with-options-undefined.js | 68 +++++ .../since/largestunit-invalid-string.js | 19 +- .../prototype/since/options-wrong-type.js | 23 ++ .../since/smallestunit-invalid-string.js | 19 +- .../prototype/subtract/options-wrong-type.js | 23 ++ .../subtract/overflow-invalid-string.js | 9 +- .../prototype/toJSON/year-format.js | 55 ++++ ...romfields-called-with-options-undefined.js | 16 ++ ...romfields-called-with-options-undefined.js | 16 ++ .../toString/fractionalseconddigits-auto.js | 23 ++ .../fractionalseconddigits-invalid-string.js | 9 +- .../fractionalseconddigits-non-integer.js | 2 +- .../toString/fractionalseconddigits-number.js | 33 +++ .../fractionalseconddigits-out-of-range.js | 12 +- .../fractionalseconddigits-undefined.js | 26 +- .../fractionalseconddigits-wrong-type.js | 24 +- .../prototype/toString/options-wrong-type.js | 23 ++ .../toString/rounding-cross-midnight.js | 13 + .../prototype/toString/rounding-direction.js | 30 +++ .../prototype/toString/roundingmode-ceil.js | 37 +++ .../prototype/toString/roundingmode-floor.js | 37 +++ .../toString/roundingmode-halfExpand.js | 37 +++ .../prototype/toString/roundingmode-trunc.js | 37 +++ .../smallestunit-fractionalseconddigits.js | 30 +++ .../toString/smallestunit-invalid-string.js | 28 +- .../toString/smallestunit-valid-units.js | 39 ++- .../prototype/toString/year-format.js | 55 ++++ ...r-dateadd-called-with-options-undefined.js | 69 +++++ .../until/largestunit-invalid-string.js | 19 +- .../prototype/until/options-wrong-type.js | 23 ++ .../until/smallestunit-invalid-string.js | 19 +- .../prototype/with/options-wrong-type.js | 23 ++ .../prototype/with/overflow-invalid-string.js | 9 +- .../withPlainDate/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 16 ++ ...buffer-detached-on-get-src-value-throws.js | 45 ---- ...ffer-detached-on-get-src-value-no-throw.js | 36 +++ ...buffer-detached-on-get-src-value-throws.js | 45 ---- .../sort/BigInt/detached-buffer-comparefn.js | 38 --- .../sort/detached-buffer-comparefn-coerce.js | 44 ---- .../sort/detached-buffer-comparefn.js | 38 --- .../prototype/sort/sort-tonumber.js | 16 +- ...d-when-species-retrieved-different-type.js | 61 ----- ...tached-when-species-retrieved-same-type.js | 64 ----- .../other-ctor-buffer-ctor-access-throws.js | 41 --- ...or-custom-species-proto-from-ctor-realm.js | 58 ----- .../other-ctor-buffer-ctor-custom-species.js | 52 ---- ...ther-ctor-buffer-ctor-not-object-throws.js | 61 ----- ...-ctor-buffer-ctor-species-access-throws.js | 45 ---- ...tor-buffer-ctor-species-not-ctor-throws.js | 47 ---- ...or-buffer-ctor-species-prototype-throws.js | 59 ----- .../same-ctor-buffer-ctor-access-throws.js | 46 ---- ...or-species-custom-proto-from-ctor-realm.js | 68 ----- .../same-ctor-buffer-ctor-species-custom.js | 60 ----- .../same-ctor-buffer-ctor-species-not-ctor.js | 49 ---- ...or-buffer-ctor-species-prototype-throws.js | 62 ----- .../same-ctor-buffer-ctor-species-throws.js | 49 ---- ...e-ctor-buffer-ctor-value-not-obj-throws.js | 65 ----- .../ctors/no-species.js | 30 +++ ...d-when-species-retrieved-different-type.js | 61 ----- ...tached-when-species-retrieved-same-type.js | 64 ----- .../other-ctor-buffer-ctor-access-throws.js | 41 --- ...or-custom-species-proto-from-ctor-realm.js | 59 ----- .../other-ctor-buffer-ctor-custom-species.js | 52 ---- ...ther-ctor-buffer-ctor-not-object-throws.js | 61 ----- ...-ctor-buffer-ctor-species-access-throws.js | 45 ---- ...tor-buffer-ctor-species-not-ctor-throws.js | 47 ---- .../other-ctor-buffer-ctor-species-null.js | 44 ---- ...or-buffer-ctor-species-prototype-throws.js | 59 ----- ...ther-ctor-buffer-ctor-species-undefined.js | 43 ---- ...s-when-species-retrieved-different-type.js | 89 ------- ...bounds-when-species-retrieved-same-type.js | 89 ------- .../same-ctor-buffer-ctor-access-throws.js | 46 ---- ...or-species-custom-proto-from-ctor-realm.js | 68 ----- .../same-ctor-buffer-ctor-species-custom.js | 60 ----- .../same-ctor-buffer-ctor-species-not-ctor.js | 49 ---- ...or-buffer-ctor-species-prototype-throws.js | 62 ----- .../same-ctor-buffer-ctor-species-throws.js | 49 ---- ...e-ctor-buffer-ctor-value-not-obj-throws.js | 65 ----- .../temporalHelpers-one-shift-time-zone.js | 80 ++++++ .../constructor-roundingIncrement-invalid.js | 11 +- .../prototype/era/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../eraYear/argument-string-invalid.js | 61 +++++ ...romfields-called-with-options-undefined.js | 15 ++ .../prototype/toString/timezone-offset.js | 19 ++ .../intl402/Temporal/TimeZone/etc-timezone.js | 79 ++++++ .../expressions/unary-plus/S11.4.6_A3_T3.js | 18 +- .../statements/for-in/S12.6.4_A7_T2.js | 26 +- 410 files changed, 10319 insertions(+), 2804 deletions(-) delete mode 100644 .jshintrc rename test/built-ins/ShadowRealm/prototype/evaluate/{globalthis-orginary-object.js => globalthis-ordinary-object.js} (81%) create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dateUntil/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js create mode 100644 test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js create mode 100644 test/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Duration/compare/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js create mode 100644 test/built-ins/Temporal/Duration/prototype/abs/basic.js create mode 100644 test/built-ins/Temporal/Duration/prototype/add/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/prototype/negated/basic.js create mode 100644 test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Duration/prototype/round/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/prototype/subtract/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toJSON/basic.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-auto.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-number.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/roundingmode-ceil.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/roundingmode-floor.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/roundingmode-halfExpand.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/roundingmode-trunc.js create mode 100644 test/built-ins/Temporal/Duration/prototype/toString/smallestunit-fractionalseconddigits.js create mode 100644 test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/all-negative.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/all-positive.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/partial-positive.js create mode 100644 test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js create mode 100644 test/built-ins/Temporal/Instant/prototype/round/rounding-direction.js create mode 100644 test/built-ins/Temporal/Instant/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-auto.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-number.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/rounding-cross-midnight.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/rounding-direction.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/roundingmode-ceil.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/roundingmode-floor.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/roundingmode-halfExpand.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/roundingmode-trunc.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/smallestunit-fractionalseconddigits.js create mode 100644 test/built-ins/Temporal/Instant/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/Instant/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js rename test/built-ins/Temporal/PlainDate/from/{argument-string-overflow.js => observable-get-overflow-argument-string.js} (100%) create mode 100644 test/built-ins/Temporal/PlainDate/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/add/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/subtract/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/with/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/compare/calendar-ignored.js create mode 100644 test/built-ins/Temporal/PlainDateTime/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/add/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-checked.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/balance.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/rounding-direction.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-divides.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-does-not-divide.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-one-day.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-basic.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-ceil-basic.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-floor-basic.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-basic.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-is-default.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-trunc-basic.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object-insufficient-data.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/throws-no-argument.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/round/throws-undefined.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-auto.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-number.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-cross-midnight.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-direction.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-ceil.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-floor.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-halfExpand.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-trunc.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-fractionalseconddigits.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/argument-not-object.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-options.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/with/options-wrong-type.js rename test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/{argument-object-insuffcient-data.js => argument-object-insufficient-data.js} (100%) create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-noniso.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-id.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-object.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/calendar-always.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js rename test/built-ins/Temporal/PlainTime/from/{argument-string-invalid.js => observable-get-overflow-argument-string-invalid.js} (100%) create mode 100644 test/built-ins/Temporal/PlainTime/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/calendar-always.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/add/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/PlainYearMonth/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/from/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/add/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/round/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/round/rounding-direction.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/since/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-auto.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-number.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-cross-midnight.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-direction.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-ceil.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-floor.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-halfExpand.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-trunc.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-fractionalseconddigits.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/until/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js delete mode 100644 test/built-ins/TypedArray/prototype/set/BigInt/array-arg-targetbuffer-detached-on-get-src-value-throws.js create mode 100644 test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js delete mode 100644 test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js delete mode 100644 test/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js delete mode 100644 test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js delete mode 100644 test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js create mode 100644 test/built-ins/TypedArrayConstructors/ctors/no-species.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js delete mode 100644 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js create mode 100644 test/harness/temporalHelpers-one-shift-time-zone.js create mode 100644 test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js create mode 100644 test/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js create mode 100644 test/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js create mode 100644 test/intl402/Temporal/Instant/prototype/toString/timezone-offset.js create mode 100644 test/intl402/Temporal/TimeZone/etc-timezone.js diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index abc0141f5a9..00000000000 --- a/.jshintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "predef": ["Intl"], - "esversion": 6 -} diff --git a/harness/propertyHelper.js b/harness/propertyHelper.js index 0ee7e21a928..7068f2560cc 100644 --- a/harness/propertyHelper.js +++ b/harness/propertyHelper.js @@ -6,13 +6,13 @@ description: | property descriptors. defines: - verifyProperty - - verifyEqualTo - - verifyWritable - - verifyNotWritable - - verifyEnumerable - - verifyNotEnumerable - - verifyConfigurable - - verifyNotConfigurable + - verifyEqualTo # deprecated + - verifyWritable # deprecated + - verifyNotWritable # deprecated + - verifyEnumerable # deprecated + - verifyNotEnumerable # deprecated + - verifyConfigurable # deprecated + - verifyNotConfigurable # deprecated ---*/ // @ts-check @@ -173,6 +173,9 @@ function isWritable(obj, name, verifyProp, value) { return writeSucceeded; } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyEqualTo(obj, name, value) { if (!isSameValue(obj[name], value)) { throw new Test262Error("Expected obj[" + String(name) + "] to equal " + value + @@ -180,6 +183,9 @@ function verifyEqualTo(obj, name, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyWritable(obj, name, verifyProp, value) { if (!verifyProp) { assert(Object.getOwnPropertyDescriptor(obj, name).writable, @@ -190,6 +196,9 @@ function verifyWritable(obj, name, verifyProp, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotWritable(obj, name, verifyProp, value) { if (!verifyProp) { assert(!Object.getOwnPropertyDescriptor(obj, name).writable, @@ -200,6 +209,9 @@ function verifyNotWritable(obj, name, verifyProp, value) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyEnumerable(obj, name) { assert(Object.getOwnPropertyDescriptor(obj, name).enumerable, "Expected obj[" + String(name) + "] to have enumerable:true."); @@ -208,6 +220,9 @@ function verifyEnumerable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotEnumerable(obj, name) { assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable, "Expected obj[" + String(name) + "] to have enumerable:false."); @@ -216,6 +231,9 @@ function verifyNotEnumerable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyConfigurable(obj, name) { assert(Object.getOwnPropertyDescriptor(obj, name).configurable, "Expected obj[" + String(name) + "] to have configurable:true."); @@ -224,6 +242,9 @@ function verifyConfigurable(obj, name) { } } +/** + * Deprecated; please use `verifyProperty` in new tests. + */ function verifyNotConfigurable(obj, name) { assert(!Object.getOwnPropertyDescriptor(obj, name).configurable, "Expected obj[" + String(name) + "] to have configurable:false."); diff --git a/harness/temporalHelpers.js b/harness/temporalHelpers.js index 3a2ed5e4d45..c9b7645b7f1 100644 --- a/harness/temporalHelpers.js +++ b/harness/temporalHelpers.js @@ -238,39 +238,6 @@ var TemporalHelpers = { }); }, - /* - * checkFractionalSecondDigitsOptionWrongType(temporalObject): - * - * Checks the string-or-number type handling of the fractionalSecondDigits - * option to the various types' toString() methods. temporalObject is an - * instance of the Temporal type under test. - */ - checkFractionalSecondDigitsOptionWrongType(temporalObject) { - // null is not a number, and converts to the string "null", which is an invalid string value - assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: null }), "null"); - // Booleans are not numbers, and convert to the strings "true" or "false", which are invalid - assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: true }), "true"); - assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: false }), "false"); - // Symbols are not numbers and cannot convert to strings - assert.throws(TypeError, () => temporalObject.toString({ fractionalSecondDigits: Symbol() }), "symbol"); - // BigInts are not numbers and convert to strings which are invalid - assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: 2n }), "bigint"); - - // Objects are not numbers and prefer their toString() methods when converting to a string - assert.throws(RangeError, () => temporalObject.toString({ fractionalSecondDigits: {} }), "plain object"); - - const toStringExpected = temporalObject.toString({ fractionalSecondDigits: 'auto' }); - const expected = [ - "get fractionalSecondDigits.toString", - "call fractionalSecondDigits.toString", - ]; - const actual = []; - const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); - const result = temporalObject.toString({ fractionalSecondDigits: observer }); - assert.sameValue(result, toStringExpected, "object with toString"); - assert.compareArray(actual, expected, "order of operations"); - }, - /* * checkPlainDateTimeConversionFastPath(func): * @@ -1034,6 +1001,44 @@ var TemporalHelpers = { return new CalendarFieldsIterable(); }, + /* + * A custom calendar that asserts its ...FromFields() methods are called with + * the options parameter having the value undefined. + */ + calendarFromFieldsUndefinedOptions() { + class CalendarFromFieldsUndefinedOptions extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCallCount = 0; + this.monthDayFromFieldsCallCount = 0; + this.yearMonthFromFieldsCallCount = 0; + } + + toString() { + return "from-fields-undef-options"; + } + + dateFromFields(fields, options) { + this.dateFromFieldsCallCount++; + assert.sameValue(options, undefined, "dateFromFields shouldn't be called with options"); + return super.dateFromFields(fields, options); + } + + yearMonthFromFields(fields, options) { + this.yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return super.yearMonthFromFields(fields, options); + } + + monthDayFromFields(fields, options) { + this.monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return super.monthDayFromFields(fields, options); + } + } + return new CalendarFromFieldsUndefinedOptions(); + }, + /* * A custom calendar that modifies the fields object passed in to * dateFromFields, sabotaging its time properties. @@ -1312,10 +1317,10 @@ var TemporalHelpers = { if (this._shiftNanoseconds > 0) { if (this._isBeforeShift(instant)) return [instant]; if (instant.epochNanoseconds < this._epoch2) return []; - return [instant.add(this._shift)]; + return [instant.subtract(this._shift)]; } if (instant.epochNanoseconds < this._epoch2) return [instant]; - const shifted = instant.add(this._shift); + const shifted = instant.subtract(this._shift); if (this._isBeforeShift(instant)) return [instant, shifted]; return [shifted]; } diff --git a/implementation-contributed/v8/mjsunit/harmony/to-number.js b/implementation-contributed/v8/mjsunit/harmony/to-number.js index a48a7d83f8c..e145782d4b9 100644 --- a/implementation-contributed/v8/mjsunit/harmony/to-number.js +++ b/implementation-contributed/v8/mjsunit/harmony/to-number.js @@ -19,6 +19,8 @@ assertEquals(NaN, %ToNumber(undefined)); assertEquals(-1, %ToNumber("-1")); assertEquals(123, %ToNumber("123")); assertEquals(NaN, %ToNumber("random text")); +assertEquals(NaN, %ToNumber("INFINITY")); +assertEquals(NaN, %ToNumber("infinity")); assertThrows(function() { %ToNumber(Symbol.toPrimitive) }, TypeError); diff --git a/test/built-ins/Function/prototype/bind/instance-length-tointeger.js b/test/built-ins/Function/prototype/bind/instance-length-tointeger.js index 876ed47b516..92aaf1a3160 100644 --- a/test/built-ins/Function/prototype/bind/instance-length-tointeger.js +++ b/test/built-ins/Function/prototype/bind/instance-length-tointeger.js @@ -13,12 +13,15 @@ info: | 5. Let targetHasLength be ? HasOwnProperty(Target, "length"). 6. If targetHasLength is true, then a. Let targetLen be ? Get(Target, "length"). - b. If Type(targetLen) is not Number, let L be 0. - c. Else, - i. Set targetLen to ! ToInteger(targetLen). - ii. Let L be the larger of 0 and the result of targetLen minus the number of elements of args. - 7. Else, let L be 0. - 8. Perform ! SetFunctionLength(F, L). + b. If Type(targetLen) is Number, then + i. If targetLen is +∞𝔽, set L to +∞. + ii. Else if targetLen is -∞𝔽, set L to 0. + iii. Else, + 1. Let targetLenAsInt be ! ToIntegerOrInfinity(targetLen). + 2. Assert: targetLenAsInt is finite. + 3. Let argCount be the number of elements in args. + 4. Set L to max(targetLenAsInt - argCount, 0). + 7. Perform ! SetFunctionLength(F, L). [...] ToInteger ( argument ) @@ -40,10 +43,12 @@ Object.defineProperty(fn, "length", {value: -0}); assert.sameValue(fn.bind().length, 0); Object.defineProperty(fn, "length", {value: Infinity}); -assert.sameValue(fn.bind().length, Infinity); +assert.sameValue(fn.bind().length, Infinity, "target length of infinity, zero bound arguments"); +assert.sameValue(fn.bind(0, 0).length, Infinity, "target length of infinity, one bound argument"); Object.defineProperty(fn, "length", {value: -Infinity}); -assert.sameValue(fn.bind().length, 0); +assert.sameValue(fn.bind().length, 0, "target length of negative infinity, zero bound arguments"); +assert.sameValue(fn.bind(0, 0).length, 0, "target length of negative infinity, one bound argument"); Object.defineProperty(fn, "length", {value: 3.66}); assert.sameValue(fn.bind().length, 3); diff --git a/test/built-ins/Number/S15.7.1.1_A1.js b/test/built-ins/Number/S15.7.1.1_A1.js index 3ccfaf32ae3..adf4f19515e 100644 --- a/test/built-ins/Number/S15.7.1.1_A1.js +++ b/test/built-ins/Number/S15.7.1.1_A1.js @@ -24,3 +24,5 @@ assert.sameValue( ); assert.sameValue(Number("abc"), NaN, 'Number("abc") returns NaN'); +assert.sameValue(Number("INFINITY"), NaN, 'Number("INFINITY") returns NaN'); +assert.sameValue(Number("infinity"), NaN, 'Number("infinity") returns NaN'); diff --git a/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js b/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js index b05d708a78d..ee964823a24 100644 --- a/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js +++ b/test/built-ins/ShadowRealm/WrappedFunction/throws-typeerror-on-revoked-proxy.js @@ -3,7 +3,7 @@ /*--- esid: sec-wrapped-function-exotic-objects-call-thisargument-argumentslist description: > - WrappedFunctionCreate throws a TypeError the target is a revoked proxy. + WrappedFunctionCreate throws a TypeError the target is a revoked proxy. info: | WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) diff --git a/test/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js b/test/built-ins/ShadowRealm/prototype/evaluate/globalthis-ordinary-object.js similarity index 81% rename from test/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js rename to test/built-ins/ShadowRealm/prototype/evaluate/globalthis-ordinary-object.js index fd71e910268..d59e77078d1 100644 --- a/test/built-ins/ShadowRealm/prototype/evaluate/globalthis-orginary-object.js +++ b/test/built-ins/ShadowRealm/prototype/evaluate/globalthis-ordinary-object.js @@ -64,3 +64,27 @@ assert.sameValue( true, 'globalThis.constructor is Object' ); + +assert.sameValue( + r.evaluate(` + let result; + try { + globalThis.__proto__ = {x: 2}; + result = true; + } catch (e) { + result = false; + } + result; + `), + true, + 'Can assign to globalThis.__proto__ directly' +); + +assert.sameValue( + r.evaluate(` + Reflect.set(globalThis, '__proto__', {x: 1}) && + Reflect.setPrototypeOf(globalThis.__proto__, {x: 2}); + `), + true, + 'Can set an ordinary globalThis.__proto__' +); diff --git a/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js b/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js index 4f1dacf0eb4..b3cec5b115e 100644 --- a/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js +++ b/test/built-ins/ShadowRealm/prototype/evaluate/throws-typeerror-wrap-throwing.js @@ -3,7 +3,7 @@ /*--- esid: sec-wrappedfunctioncreate description: > - WrappedFunctionCreate throws a TypeError if the accessing target's property may throw. + WrappedFunctionCreate throws a TypeError if the accessing target's property may throw. info: | WrappedFunctionCreate ( callerRealm: a Realm Record, Target: a function object, ) diff --git a/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js b/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js index 06d9453fa10..55fd38f54b0 100644 --- a/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js +++ b/test/built-ins/String/prototype/localeCompare/15.5.4.9_CE.js @@ -1,15 +1,21 @@ // Copyright 2012 Norbert Lindenberg. All rights reserved. // Copyright 2012 Mozilla Corporation. All rights reserved. // Copyright 2013 Microsoft Corporation. All rights reserved. +// Copyright (C) 2022 Richard Gibson. All rights reserved. // This code is governed by the license found in the LICENSE file. /*--- -es5id: 15.5.4.9_CE description: > - Tests that String.prototype.localeCompare returns 0 when - comparing Strings that are considered canonically equivalent by - the Unicode standard. -author: Norbert Lindenberg + String.prototype.localeCompare must return 0 when + comparing Strings that are considered canonically equivalent by + the Unicode Standard. +esid: sec-string.prototype.localecompare +info: | + String.prototype.localeCompare ( _that_ [ , _reserved1_ [ , _reserved2_ ] ] ) + + This function must treat Strings that are canonically equivalent + according to the Unicode standard as identical and must return `0` + when comparing Strings that are considered canonically equivalent. ---*/ // pairs with characters not in Unicode 3.0 are commented out @@ -49,26 +55,12 @@ var pairs = [ // ["\uD87E\uDC2B", "北"] ]; -// Detect whether we are using locale-sensitive comparisons or a bitwise comparison -if ("a".localeCompare("Z") < 0) { - // We are using locale-sensitive comparison, so all pairs should be canonically equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) !== 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); - } - } -} else { - // We are using bitwise comparison, so all pairs should not be equivalent - var i; - for (i = 0; i < pairs.length; i++) { - var pair = pairs[i]; - if (pair[0].localeCompare(pair[1]) === 0) { - throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + - ") = " + pair[1] + " (" + toU(pair[1]) + ")."); - } +var i; +for (i = 0; i < pairs.length; i++) { + var pair = pairs[i]; + if (pair[0].localeCompare(pair[1]) !== 0) { + throw new Test262Error("String.prototype.localeCompare considers " + pair[0] + " (" + toU(pair[0]) + + ") ≠ " + pair[1] + " (" + toU(pair[1]) + ")."); } } diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js new file mode 100644 index 00000000000..834d82a7ebb --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateadd +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateAdd(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..b76329860a7 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.js new file mode 100644 index 00000000000..8f135256c93 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/options-wrong-type.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.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}`); +}; diff --git a/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js index 3197c54007c..df173c933f7 100644 --- a/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/dateAdd/overflow-invalid-string.js @@ -17,6 +17,11 @@ features: [Temporal, arrow-function] const calendar = new Temporal.Calendar("iso8601"); const date = new Temporal.PlainDate(2000, 5, 2, calendar); const duration = new Temporal.Duration(3, 3, 0, 3); -assert.throws(RangeError, - () => calendar.dateAdd(date, duration, { overflow: "other string" }), - "Value for overflow not one of the allowed string values"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateAdd(date, duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.js new file mode 100644 index 00000000000..011851c7550 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/options-wrong-type.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.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}`); +}; diff --git a/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js index 6cc0d01724d..28e81de7ceb 100644 --- a/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/dateFromFields/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal, arrow-function] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, - { overflow: "other string" }), - "Value for overflow not one of the allowed string values"); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.dateFromFields({ year: 2000, month: 5, day: 2 }, + { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js new file mode 100644 index 00000000000..a3ecc5814d1 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateUntil/argument-string-invalid.js @@ -0,0 +1,67 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dateuntil +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +const other = new Temporal.PlainDate(2020, 1, 1, instance); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dateUntil(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => instance.dateUntil(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/dateUntil/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..419334f252e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateUntil/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/dateUntil/options-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/dateUntil/options-wrong-type.js new file mode 100644 index 00000000000..1191edf29fe --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dateUntil/options-wrong-type.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.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}`); +}; diff --git a/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js new file mode 100644 index 00000000000..95a33903b79 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/day/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.day +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.day(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/day/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..80cd4dae2e1 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/day/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js new file mode 100644 index 00000000000..77d600bffde --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..e67d34fdcc0 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfWeek/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js new file mode 100644 index 00000000000..8768faa6381 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.dayofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.dayOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..2ebc1c96f30 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/dayOfYear/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js new file mode 100644 index 00000000000..97ecac0fa8f --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinmonth +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInMonth(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..86e25eb109a --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInMonth/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js new file mode 100644 index 00000000000..9c98bd32957 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinweek +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInWeek(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..68e86ffc1e5 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInWeek/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js new file mode 100644 index 00000000000..8d92ef970d0 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.daysinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.daysInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/daysInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..20b64607d61 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/daysInYear/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js new file mode 100644 index 00000000000..6a1c1d5d6b7 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.inleapyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.inLeapYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js new file mode 100644 index 00000000000..1c4272fbd72 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/argument-string.js @@ -0,0 +1,26 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js index 4359c4c8d44..7e8d3cf048b 100644 --- a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/basic.js @@ -8,10 +8,19 @@ features: [Temporal] ---*/ const iso = Temporal.Calendar.from("iso8601"); -const res = false; -assert.sameValue(iso.inLeapYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); -assert.sameValue(iso.inLeapYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); -assert.sameValue(iso.inLeapYear(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js index 8b3e5de8a2f..003cf490ab0 100644 --- a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/branding.js @@ -11,12 +11,14 @@ const inLeapYear = Temporal.Calendar.prototype.inLeapYear; assert.sameValue(typeof inLeapYear, "function"); -assert.throws(TypeError, () => inLeapYear.call(undefined), "undefined"); -assert.throws(TypeError, () => inLeapYear.call(null), "null"); -assert.throws(TypeError, () => inLeapYear.call(true), "true"); -assert.throws(TypeError, () => inLeapYear.call(""), "empty string"); -assert.throws(TypeError, () => inLeapYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => inLeapYear.call(1), "1"); -assert.throws(TypeError, () => inLeapYear.call({}), "plain object"); -assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 3, 4); + +assert.throws(TypeError, () => inLeapYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => inLeapYear.call(null, arg), "null"); +assert.throws(TypeError, () => inLeapYear.call(true, arg), "true"); +assert.throws(TypeError, () => inLeapYear.call("", arg), "empty string"); +assert.throws(TypeError, () => inLeapYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => inLeapYear.call(1, arg), "1"); +assert.throws(TypeError, () => inLeapYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => inLeapYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); diff --git a/test/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..2b89a6b531a --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/inLeapYear/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js b/test/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js new file mode 100644 index 00000000000..72483362e8b --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/mergeFields/basic.js @@ -0,0 +1,33 @@ +// 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" +); diff --git a/test/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js b/test/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js new file mode 100644 index 00000000000..e322a791e13 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/mergeFields/iso8601-calendar-month-monthCode.js @@ -0,0 +1,99 @@ +// 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" +); diff --git a/test/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js b/test/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js new file mode 100644 index 00000000000..2908be90ba8 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/mergeFields/non-string-properties.js @@ -0,0 +1,34 @@ +// 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: Only string 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] +includes: [deepEqual.js] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +assert.deepEqual( + cal.mergeFields({ 1: 2 }, { 3: 4 }), + { "1": 2, "3": 4 }, + "number keys are actually string keys and are merged as such" +); +assert.deepEqual( + 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"); +assert.deepEqual(cal.mergeFields({ [foo]: 1 }, { [bar]: 2 }), {}, "symbol keys are not merged"); diff --git a/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js new file mode 100644 index 00000000000..e314a1d01e3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/month/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.month +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.month(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/month/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..77c6e75f829 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/month/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js new file mode 100644 index 00000000000..3994dee3bc9 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthCode/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthcode +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthCode(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/monthCode/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..18111f2f165 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthCode/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js new file mode 100644 index 00000000000..e79389fe36e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/basic.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.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. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +let result = cal.monthDayFromFields({ year: 2021, month: 7, day: 3 }); +TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "month 7, day 3, with year"); +result = cal.monthDayFromFields({ year: 2021, month: 12, day: 31 }); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 12, day 31, with year"); +result = cal.monthDayFromFields({ monthCode: "M07", day: 3 }); +TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "monthCode M07, day 3"); +result = cal.monthDayFromFields({ monthCode: "M12", day: 31 }); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "monthCode M12, day 31"); + +["constrain", "reject"].forEach(function (overflow) { + const opt = { overflow }; + result = cal.monthDayFromFields({ year: 2021, month: 7, day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "month 7, day 3, with year"); + result = cal.monthDayFromFields({ year: 2021, month: 12, day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "month 12, day 31, with year"); + result = cal.monthDayFromFields({ monthCode: "M07", day: 3 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M07", 3, "monthCode M07, day 3"); + result = cal.monthDayFromFields({ monthCode: "M12", day: 31 }, opt); + TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "monthCode M12, day 31"); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js new file mode 100644 index 00000000000..d642ab4302e --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-missing-properties.js @@ -0,0 +1,24 @@ +// 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. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, 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({ 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({ month: 1, day: 17 }), "year is required if month is present"); +assert.throws(TypeError, () => cal.monthDayFromFields({ year: 2021, day: 17 }), "either month or monthCode is required"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js index f8400f71854..88c229f074c 100644 --- a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/fields-not-object.js @@ -7,7 +7,7 @@ description: Throw a TypeError if the fields is not an object features: [Symbol, Temporal] ---*/ -const tests = [undefined, null, false, "string", Symbol("sym"), Math.PI, 42n]; +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; const iso = Temporal.Calendar.from("iso8601"); for (const fields of tests) { assert.throws(TypeError, () => iso.monthDayFromFields(fields, {})); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js new file mode 100644 index 00000000000..29e5c4f0984 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/monthcode-invalid.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.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`); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.js new file mode 100644 index 00000000000..f19f381f5d0 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/options-wrong-type.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.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}`); +}; diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js new file mode 100644 index 00000000000..0ad71fe6d07 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-constrain.js @@ -0,0 +1,91 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.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. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); +const opt = { overflow: "constrain" }; + +let result = cal.monthDayFromFields({ year: 2021, month: 1, day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M01", 31, "day is constrained to 31 in month 1"); +result = cal.monthDayFromFields({ year: 2021, month: 2, day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M02", 28, "day is constrained to 28 in month 2 (year 2021)"); +result = cal.monthDayFromFields({ year: 2021, month: 3, day: 9033 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M03", 31, "day is constrained to 31 in month 3"); +result = cal.monthDayFromFields({ year: 2021, month: 4, day: 50 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M04", 30, "day is constrained to 30 in month 4"); +result = cal.monthDayFromFields({ year: 2021, month: 5, day: 77 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M05", 31, "day is constrained to 31 in month 5"); +result = cal.monthDayFromFields({ year: 2021, month: 6, day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M06", 30, "day is constrained to 30 in month 6"); +result = cal.monthDayFromFields({ year: 2021, month: 7, day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M07", 31, "day is constrained to 31 in month 7"); +result = cal.monthDayFromFields({ year: 2021, month: 8, day: 300 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M08", 31, "day is constrained to 31 in month 8"); +result = cal.monthDayFromFields({ year: 2021, month: 9, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M09", 30, "day is constrained to 30 in month 9"); +result = cal.monthDayFromFields({ year: 2021, month: 10, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M10", 31, "day is constrained to 31 in month 10"); +result = cal.monthDayFromFields({ year: 2021, month: 11, day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M11", 30, "day is constrained to 30 in month 11"); +result = cal.monthDayFromFields({ year: 2021, month: 12, day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "day is constrained to 31 in month 12"); + +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: -99999, day: 1 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: -1, day: 1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.monthDayFromFields({ year: 2021, month: 0, day: 1 }, opt), + "month zero is out of range even with overflow constrain" +) + +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 constrained to 31"); + +result = cal.monthDayFromFields({ monthCode: "M01", day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M01", 31, "day is constrained to 31 in monthCode M01"); +result = cal.monthDayFromFields({ monthCode: "M02", day: 133 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M02", 29, "day is constrained to 29 in monthCode M02"); +result = cal.monthDayFromFields({ monthCode: "M03", day: 9033 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M03", 31, "day is constrained to 31 in monthCode M03"); +result = cal.monthDayFromFields({ monthCode: "M04", day: 50 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M04", 30, "day is constrained to 30 in monthCode M04"); +result = cal.monthDayFromFields({ monthCode: "M05", day: 77 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M05", 31, "day is constrained to 31 in monthCode M05"); +result = cal.monthDayFromFields({ monthCode: "M06", day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M06", 30, "day is constrained to 30 in monthCode M06"); +result = cal.monthDayFromFields({ monthCode: "M07", day: 33 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M07", 31, "day is constrained to 31 in monthCode M07"); +result = cal.monthDayFromFields({ monthCode: "M08", day: 300 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M08", 31, "day is constrained to 31 in monthCode M08"); +result = cal.monthDayFromFields({ monthCode: "M09", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M09", 30, "day is constrained to 30 in monthCode M09"); +result = cal.monthDayFromFields({ monthCode: "M10", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M10", 31, "day is constrained to 31 in monthCode M10"); +result = cal.monthDayFromFields({ monthCode: "M11", day: 400 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M11", 30, "day is constrained to 30 in monthCode M11"); +result = cal.monthDayFromFields({ monthCode: "M12", day: 500 }, opt); +TemporalHelpers.assertPlainMonthDay(result, "M12", 31, "day is constrained to 31 in monthCode M12"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js index 2e87dc1a67a..6844c7e3d2b 100644 --- a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-invalid-string.js @@ -17,4 +17,11 @@ features: [Temporal] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.monthDayFromFields({ year: 2000, month: 5, day: 2 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js new file mode 100644 index 00000000000..5db608b3359 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/overflow-reject.js @@ -0,0 +1,64 @@ +// 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. Let result be ? ISOMonthDayFromFields(fields, options). + 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[ReferenceISOYear]]). +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` + ); +}); + +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M01", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M01"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M02", day: 30 }, { overflow: "reject" }), "Day 30 is out of range for monthCode M02"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M03", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M03"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M04", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M04"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M05", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M05"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M06", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M06"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M07", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M07"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M08", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M08"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M09", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M09"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M10", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M10"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M11", day: 31 }, { overflow: "reject" }), "Day 31 is out of range for monthCode M11"); +assert.throws(RangeError, () => cal.monthDayFromFields( + { monthCode: "M12", day: 32 }, { overflow: "reject" }), "Day 32 is out of range for monthCode M12"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js new file mode 100644 index 00000000000..e0b942007d6 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthDayFromFields/reference-year-1972.js @@ -0,0 +1,23 @@ +// 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: Use a leap year as the reference year if monthCode is given +info: | + sec-temporal-isomonthdayfromfields: + 12. If _monthCode_ is *undefined*, then + a. Let _result_ be ? RegulateISODate(_year_, _month_, _day_, _overflow_). + 13. Else, + a. Let _result_ be ? RegulateISODate(_referenceISOYear_, _month_, _day_, _overflow_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +let result = cal.monthDayFromFields({ year: 2021, monthCode: "M02", day: 29 }); +TemporalHelpers.assertPlainMonthDay(result, "M02", 29, "year is ignored and reference year should be a leap year if monthCode is given"); + +result = cal.monthDayFromFields({ year: 2021, month: 2, day: 29 }, { overflow: "constrain" }); +TemporalHelpers.assertPlainMonthDay(result, "M02", 28, "year should not be ignored if monthCode is not given"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js new file mode 100644 index 00000000000..811a6e00cb3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.monthsinyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.monthsInYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js new file mode 100644 index 00000000000..9a8748d8771 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/argument-string.js @@ -0,0 +1,18 @@ +// 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); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js index fcf4e35084a..9edcee17457 100644 --- a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/basic.js @@ -9,9 +9,9 @@ features: [Temporal] const iso = Temporal.Calendar.from("iso8601"); const res = 12; -assert.sameValue(iso.monthsInYear(Temporal.PlainDate.from("1994-11-05")), res, "PlainDate"); -assert.sameValue(iso.monthsInYear(Temporal.PlainDateTime.from("1994-11-05T08:15:30")), res, "PlainDateTime"); -assert.sameValue(iso.monthsInYear(Temporal.PlainYearMonth.from("1994-11")), res, "PlainYearMonth"); +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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js index e86c5f50e22..4d16a000786 100644 --- a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/branding.js @@ -11,12 +11,14 @@ const monthsInYear = Temporal.Calendar.prototype.monthsInYear; assert.sameValue(typeof monthsInYear, "function"); -assert.throws(TypeError, () => monthsInYear.call(undefined), "undefined"); -assert.throws(TypeError, () => monthsInYear.call(null), "null"); -assert.throws(TypeError, () => monthsInYear.call(true), "true"); -assert.throws(TypeError, () => monthsInYear.call(""), "empty string"); -assert.throws(TypeError, () => monthsInYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => monthsInYear.call(1), "1"); -assert.throws(TypeError, () => monthsInYear.call({}), "plain object"); -assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 3, 4); + +assert.throws(TypeError, () => monthsInYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => monthsInYear.call(null, arg), "null"); +assert.throws(TypeError, () => monthsInYear.call(true, arg), "true"); +assert.throws(TypeError, () => monthsInYear.call("", arg), "empty string"); +assert.throws(TypeError, () => monthsInYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => monthsInYear.call(1, arg), "1"); +assert.throws(TypeError, () => monthsInYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => monthsInYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); diff --git a/test/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..838aff96f6f --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/monthsInYear/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js new file mode 100644 index 00000000000..5f9f4da0d49 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindate.js @@ -0,0 +1,76 @@ +// 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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js new file mode 100644 index 00000000000..e7546bb7119 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-plaindatetime.js @@ -0,0 +1,76 @@ +// 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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js new file mode 100644 index 00000000000..7b8e721b7e3 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.weekofyear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.weekOfYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js new file mode 100644 index 00000000000..f031d046900 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/argument-string.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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"); diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js index 82f80e27c74..d6b5a0f0cf1 100644 --- a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/branding.js @@ -11,12 +11,14 @@ const weekOfYear = Temporal.Calendar.prototype.weekOfYear; assert.sameValue(typeof weekOfYear, "function"); -assert.throws(TypeError, () => weekOfYear.call(undefined), "undefined"); -assert.throws(TypeError, () => weekOfYear.call(null), "null"); -assert.throws(TypeError, () => weekOfYear.call(true), "true"); -assert.throws(TypeError, () => weekOfYear.call(""), "empty string"); -assert.throws(TypeError, () => weekOfYear.call(Symbol()), "symbol"); -assert.throws(TypeError, () => weekOfYear.call(1), "1"); -assert.throws(TypeError, () => weekOfYear.call({}), "plain object"); -assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = new Temporal.PlainDate(2021, 7, 20); + +assert.throws(TypeError, () => weekOfYear.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => weekOfYear.call(null, arg), "null"); +assert.throws(TypeError, () => weekOfYear.call(true, arg), "true"); +assert.throws(TypeError, () => weekOfYear.call("", arg), "empty string"); +assert.throws(TypeError, () => weekOfYear.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => weekOfYear.call(1, arg), "1"); +assert.throws(TypeError, () => weekOfYear.call({}, arg), "plain object"); +assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => weekOfYear.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); diff --git a/test/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..c75c1d52145 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/weekOfYear/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js b/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js new file mode 100644 index 00000000000..e186a2321f8 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/year/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.year +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.year(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/Calendar/prototype/year/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..31549636a44 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/year/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.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); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js new file mode 100644 index 00000000000..2624bc7b651 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/basic.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields return correctly with valid data. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +let result = cal.yearMonthFromFields({ year: 2021, month: 7 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, month 7"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, month 12"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "year 2021, monthCode M07"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "year 2021, monthCode M12"); + +["constrain", "reject"].forEach((overflow) => { + const opt = { overflow }; + result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, month 7, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, month 12, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", `year 2021, monthCode M07, overflow ${overflow}`); + result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); + TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", `year 2021, monthCode M12, overflow ${overflow}`); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js index 0839394ca96..7212b7f1d6c 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/branding.js @@ -11,12 +11,14 @@ const yearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; assert.sameValue(typeof yearMonthFromFields, "function"); -assert.throws(TypeError, () => yearMonthFromFields.call(undefined), "undefined"); -assert.throws(TypeError, () => yearMonthFromFields.call(null), "null"); -assert.throws(TypeError, () => yearMonthFromFields.call(true), "true"); -assert.throws(TypeError, () => yearMonthFromFields.call(""), "empty string"); -assert.throws(TypeError, () => yearMonthFromFields.call(Symbol()), "symbol"); -assert.throws(TypeError, () => yearMonthFromFields.call(1), "1"); -assert.throws(TypeError, () => yearMonthFromFields.call({}), "plain object"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar), "Temporal.Calendar"); -assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype), "Temporal.Calendar.prototype"); +const arg = { year: 2021, month: 1 }; + +assert.throws(TypeError, () => yearMonthFromFields.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => yearMonthFromFields.call(null, arg), "null"); +assert.throws(TypeError, () => yearMonthFromFields.call(true, arg), "true"); +assert.throws(TypeError, () => yearMonthFromFields.call("", arg), "empty string"); +assert.throws(TypeError, () => yearMonthFromFields.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => yearMonthFromFields.call(1, arg), "1"); +assert.throws(TypeError, () => yearMonthFromFields.call({}, arg), "plain object"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar, arg), "Temporal.Calendar"); +assert.throws(TypeError, () => yearMonthFromFields.call(Temporal.Calendar.prototype, arg), "Temporal.Calendar.prototype"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js new file mode 100644 index 00000000000..c63d8f39e6c --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-missing-properties.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will throw TypeError with incorrect input data type. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") + +assert.throws(TypeError, () => cal.yearMonthFromFields({}), "at least one correctly spelled property is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ month: 1 }), "year is required"); +assert.throws(TypeError, () => cal.yearMonthFromFields({ year: 2021 }), "month or monthCode is required"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js index 7969ba6e441..e04972b2dde 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/fields-not-object.js @@ -7,7 +7,7 @@ description: Throw a TypeError if the fields is not an object features: [Symbol, Temporal] ---*/ -const tests = [undefined, null, false, "string", Symbol("sym"), Math.PI, 42n]; +const tests = [undefined, null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; const iso = Temporal.Calendar.from("iso8601"); for (const fields of tests) { assert.throws(TypeError, () => iso.yearMonthFromFields(fields, {})); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js new file mode 100644 index 00000000000..0b01bf85a75 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/monthcode-invalid.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for an out-of-range, conflicting, or ill-formed monthCode +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +["m1", "M1", "m01"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not well-formed`); +}); + +assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, month: 12, monthCode: "M11" }), + "monthCode and month conflict"); + +["M00", "M19", "M99", "M13"].forEach((monthCode) => { + assert.throws(RangeError, () => cal.yearMonthFromFields({ year: 2021, monthCode }), + `monthCode '${monthCode}' is not valid for year 2021`); +}); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js new file mode 100644 index 00000000000..0246e70bbcc --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-not-object.js @@ -0,0 +1,17 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw a TypeError if options is not an object or undefined +info: | + 5. Set options to ? GetOptionsObject(options). +features: [Symbol, Temporal] +---*/ + +const tests = [null, true, false, "string", Symbol("sym"), Math.PI, Infinity, NaN, 42n]; +const iso = new Temporal.Calendar("iso8601"); +for (const options of tests) { + assert.throws(TypeError, () => iso.yearMonthFromFields({ year: 2021, month: 7 }, options), + "options is not object"); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.js new file mode 100644 index 00000000000..625fcec62a5 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/options-wrong-type.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.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}`); +}; diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js new file mode 100644 index 00000000000..6384d42a285 --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-constrain.js @@ -0,0 +1,91 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Temporal.Calendar.prototype.yearMonthFromFields will return correctly with data and overflow set to 'constrain'. +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601") +const opt = { overflow: "constrain" }; + +let result = cal.yearMonthFromFields({ year: 2021, month: 1 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "month 1 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 2 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "month 2 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 3 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "month 3 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 4 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "month 4 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 5 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "month 5 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 6 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "month 6 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 7 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "month 7 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 8 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "month 8 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 9 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "month 9 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 10 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "month 10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 11 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "month 11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, month: 12 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 12 with overflow constrain"); + +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -99999 }, opt), + "negative month -99999 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: -1 }, opt), + "negative month -1 is out of range even with overflow constrain" +) +assert.throws( + RangeError, + () => cal.yearMonthFromFields({ year: 2021, month: 0 }, opt), + "month zero is out of range even with overflow constrain" +) + +result = cal.yearMonthFromFields({ year: 2021, month: 13 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 13 is constrained to 12"); +result = cal.yearMonthFromFields({ year: 2021, month: 99999 }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "month 99999 is constrained to 12"); + +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M01" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 1, "M01", "monthCode M01 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M02" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 2, "M02", "monthCode M02 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M03" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 3, "M03", "monthCode M03 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M04" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 4, "M04", "monthCode M04 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M05" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 5, "M05", "monthCode M05 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M06" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 6, "M06", "monthCode M06 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M07" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 7, "M07", "monthCode M07 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M08" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 8, "M08", "monthCode M08 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M09" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 9, "M09", "monthCode M09 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M10" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 10, "M10", "monthCode M10 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M11" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 11, "M11", "monthCode M11 with overflow constrain"); +result = cal.yearMonthFromFields({ year: 2021, monthCode: "M12" }, opt); +TemporalHelpers.assertPlainYearMonth(result, 2021, 12, "M12", "monthCode M12 with overflow constrain"); diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js index 99ffe6af277..77c14141097 100644 --- a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-invalid-string.js @@ -17,4 +17,11 @@ features: [Temporal] ---*/ const calendar = new Temporal.Calendar("iso8601"); -assert.throws(RangeError, () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => calendar.yearMonthFromFields({ year: 2000, month: 5 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js new file mode 100644 index 00000000000..d0d475d9e7b --- /dev/null +++ b/test/built-ins/Temporal/Calendar/prototype/yearMonthFromFields/overflow-reject.js @@ -0,0 +1,26 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.yearmonthfromfields +description: Throw RangeError for input data out of range with overflow reject +info: | + 1. Let calendar be the this value. + 2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]). + 3. Assert: calendar.[[Identifier]] is "iso8601". + 4. If Type(fields) is not Object, throw a TypeError exception. + 5. Set options to ? GetOptionsObject(options). + 6. Let result be ? ISOYearMonthFromFields(fields, options). + 7. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[ReferenceISODay]]). +features: [Temporal] +---*/ + +const cal = new Temporal.Calendar("iso8601"); + +[-1, 0, 13, 9995].forEach((month) => { + assert.throws( + RangeError, + () => cal.yearMonthFromFields({year: 2021, month, day: 5}, { overflow: "reject" }), + `Month ${month} is out of range for 2021 with overflow: reject` + ); +}); diff --git a/test/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 00000000000..c2169e338a3 --- /dev/null +++ b/test/built-ins/Temporal/Duration/compare/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +const duration1 = new Temporal.Duration(0, 0, 1); +const duration2 = new Temporal.Duration(0, 0, 1); +Temporal.Duration.compare(duration1, duration2, { relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 4); +// one call in CalculateOffsetShift for each duration argument, plus one in +// UnbalanceDurationRelative for each duration argument diff --git a/test/built-ins/Temporal/Duration/compare/options-wrong-type.js b/test/built-ins/Temporal/Duration/compare/options-wrong-type.js new file mode 100644 index 00000000000..427dd9fee8c --- /dev/null +++ b/test/built-ins/Temporal/Duration/compare/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.Duration.compare({ hours: 1 }, { minutes: 60 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js b/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js new file mode 100644 index 00000000000..9aeee2d44b5 --- /dev/null +++ b/test/built-ins/Temporal/Duration/compare/twenty-five-hour-day.js @@ -0,0 +1,33 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +description: Unbalancing handles DST days with more than 24 hours +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tz = TemporalHelpers.springForwardFallBackTimeZone(); + +// 2000-10-29 is a 25-hour day according to this time zone... + +const relativeTo = new Temporal.ZonedDateTime(941187600_000_000_000n, tz); + +// confirm that we have rewound one year and one day: +assert.sameValue('1999-10-29T01:00:00-08:00[Custom/Spring_Fall]', relativeTo.toString()); + +const d1 = new Temporal.Duration(1, 0, 0, 1); +const d2 = new Temporal.Duration(1, 0, 0, 0, 25); + +// ...so the durations should be equal relative to relativeTo: + +assert.sameValue(0, + Temporal.Duration.compare(d1, d2, { relativeTo }), + "2000-10-29 is a 25-hour day" +); + +assert.sameValue(1, + Temporal.Duration.compare(d1, { years: 1, hours: 24 }, { relativeTo }), + "2020-10-29 has more than 24 hours" +); diff --git a/test/built-ins/Temporal/Duration/prototype/abs/basic.js b/test/built-ins/Temporal/Duration/prototype/abs/basic.js new file mode 100644 index 00000000000..ecc2ecf18a2 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/abs/basic.js @@ -0,0 +1,39 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.abs +description: Temporal.Duration.prototype.abs will return absolute value of the input duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). + +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.abs(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "empty"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "positive"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.abs(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, "large positive"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.abs(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "negative"); + +// Test with some zeros +let d5 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d5.abs(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, "some zeros"); + +let d6 = new Temporal.Duration(0, 2, 0, 4, 0, 6, 0, 8, 0, 10); +TemporalHelpers.assertDuration( + d6.abs(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, "other zeros"); diff --git a/test/built-ins/Temporal/Duration/prototype/add/options-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/add/options-wrong-type.js new file mode 100644 index 00000000000..37500a0214b --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/add/options-wrong-type.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.duration.prototype.add +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.Duration(0, 0, 0, 0, 1); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.add({ hours: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/prototype/negated/basic.js b/test/built-ins/Temporal/Duration/prototype/negated/basic.js new file mode 100644 index 00000000000..f2bae4848a7 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/negated/basic.js @@ -0,0 +1,51 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.negated +description: Temporal.Duration.prototype.negated will return negated value of the input duration. +info: | + 3. Return ? CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.negated(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "zeros"); + +let d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.negated(), -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, + "positive values"); + +let d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.negated(), -1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5, + "large positive values"); + +let d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.negated(), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + "negative values"); + +let d5 = new Temporal.Duration(-1e5, -2e5, -3e5, -4e5, -5e5, -6e5, -7e5, -8e5, -9e5, -10e5); +TemporalHelpers.assertDuration( + d5.negated(), 1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5, + "large negative values"); + +let d6 = new Temporal.Duration(1, 0, 3, 0, 5, 0, 7, 0, 9, 0); +TemporalHelpers.assertDuration( + d6.negated(), -1, 0, -3, 0, -5, 0, -7, 0, -9, 0, + "some zeros with positive values"); + +let d7 = new Temporal.Duration(-1, 0, -3, 0, -5, 0, -7, 0, -9, 0); +TemporalHelpers.assertDuration( + d7.negated(), 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, + "some zeros with negative values"); + +let d8 = new Temporal.Duration(0, -2, 0, -4, 0, -6, 0, -8, 0, -10); +TemporalHelpers.assertDuration( + d8.negated(), 0, 2, 0, 4, 0, 6, 0, 8, 0, 10, + "other zeros with negative values"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 00000000000..2c81eabfa02 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,73 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Rounding with smallestUnit a calendar unit. +// The calls come from these paths: +// Duration.round() -> +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDurationRelative -> +// MoveRelativeDate -> calendar.dateAdd() (2x) +// calendar.dateAdd() +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); +instance1.round({ smallestUnit: "days", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 9, "rounding with calendar smallestUnit"); + +// Rounding with a non-default largestUnit to cover the path in +// UnbalanceDurationRelative where larger units are converted into smaller +// units; and with a smallestUnit larger than days to cover the path in +// RoundDuration where days are converted into larger units. +// The calls come from these paths: +// Duration.round() -> +// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() (5x) +// BalanceDurationRelative +// MoveRelativeDate -> calendar.dateAdd() +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +const instance2 = new Temporal.Duration(0, 1, 1, 1); +instance2.round({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 9, "rounding with non-default largestUnit and calendar smallestUnit"); + +// Rounding with smallestUnit a non-calendar unit, and having the resulting time +// difference be longer than a calendar day, covering the paths that go through +// AdjustRoundedDurationDays. +// The calls come from these paths: +// Duration.round() -> +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AddDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +const instance3 = new Temporal.Duration(0, 0, 0, 0, 23, 59, 59, 999, 999, 999); +instance3.round({ largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 7, "rounding with time difference exceeding calendar day"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/options-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/round/options-wrong-type.js new file mode 100644 index 00000000000..a224a6e737a --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/round/options-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-temporal.duration.prototype.round +description: TypeError thrown when options argument is missing or a non-string primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.Duration(0, 0, 0, 0, 1); +assert.throws(TypeError, () => instance.round(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.round(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js index 3d5d884b527..0904c0ccc84 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/round/smallestunit-invalid-string.js @@ -8,4 +8,20 @@ features: [Temporal] ---*/ const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => duration.round({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => duration.round({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/Duration/prototype/subtract/options-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/subtract/options-wrong-type.js new file mode 100644 index 00000000000..4bb257b88b2 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/subtract/options-wrong-type.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.duration.prototype.subtract +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.Duration(0, 0, 0, 0, 1); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.subtract({ hours: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js b/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js new file mode 100644 index 00000000000..8cadc51661c --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toJSON/basic.js @@ -0,0 +1,240 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tojson +description: Temporal.Duration.prototype.toJSON will return correct iso8601 string for the given duration. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "auto"). +features: [Temporal] +---*/ + +let d = new Temporal.Duration(); +assert.sameValue(d.toJSON(), "PT0S", "zero duration"); + +d = new Temporal.Duration(1); +assert.sameValue(d.toJSON(), "P1Y", "positive small years"); +d = new Temporal.Duration(-1); +assert.sameValue(d.toJSON(), "-P1Y", "negative small years"); +d = new Temporal.Duration(1234567890); +assert.sameValue(d.toJSON(), "P1234567890Y", "positive large years"); +d = new Temporal.Duration(-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890Y", "negative large years"); + +d = new Temporal.Duration(1, 2); +assert.sameValue(d.toJSON(), "P1Y2M", "positive years and months"); +d = new Temporal.Duration(-1, -2); +assert.sameValue(d.toJSON(), "-P1Y2M", "negative years and months"); +d = new Temporal.Duration(0, 2); +assert.sameValue(d.toJSON(), "P2M", "positive small months"); +d = new Temporal.Duration(0,-2); +assert.sameValue(d.toJSON(), "-P2M", "negative small months"); +d = new Temporal.Duration(0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890M", "positive large months"); +d = new Temporal.Duration(0,-1234567890); +assert.sameValue(d.toJSON(), "-P1234567890M", "negative large months"); + +d = new Temporal.Duration(1, 2, 3); +assert.sameValue(d.toJSON(), "P1Y2M3W", "positive years, months, weeks"); +d = new Temporal.Duration(-1, -2, -3); +assert.sameValue(d.toJSON(), "-P1Y2M3W", "negative years, months, weeks"); +d = new Temporal.Duration(0, 0, 3); +assert.sameValue(d.toJSON(), "P3W", "positive small weeks"); +d = new Temporal.Duration(0, 0, -3); +assert.sameValue(d.toJSON(), "-P3W", "negative small weeks"); +d = new Temporal.Duration(1, 0, 3); +assert.sameValue(d.toJSON(), "P1Y3W", "positive years and weeks"); +d = new Temporal.Duration(-1, 0, -3); +assert.sameValue(d.toJSON(), "-P1Y3W", "negative years and weeks"); +d = new Temporal.Duration(0, 2, 3); +assert.sameValue(d.toJSON(), "P2M3W", "positive months and weeks"); +d = new Temporal.Duration(0, -2, -3); +assert.sameValue(d.toJSON(), "-P2M3W", "negative months and weeks"); +d = new Temporal.Duration(0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890W", "positive large weeks"); +d = new Temporal.Duration(0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890W", "negative large weeks"); + +d = new Temporal.Duration(1, 2, 3, 4); +assert.sameValue(d.toJSON(), "P1Y2M3W4D", "positive years, months, weeks, days"); +d = new Temporal.Duration(-1, -2, -3, -4); +assert.sameValue(d.toJSON(), "-P1Y2M3W4D", "negative years, months, weeks, days"); +d = new Temporal.Duration(0, 0, 0, 1234567890); +assert.sameValue(d.toJSON(), "P1234567890D", "positive large days"); +d = new Temporal.Duration(0, 0, 0, -1234567890); +assert.sameValue(d.toJSON(), "-P1234567890D", "negative large days"); +d = new Temporal.Duration(0, 0, 0, 4); +assert.sameValue(d.toJSON(), "P4D", "positive small days"); +d = new Temporal.Duration(0, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P4D", "negative small days"); +d = new Temporal.Duration(1, 0, 0, 4); +assert.sameValue(d.toJSON(), "P1Y4D", "positive years and days"); +d = new Temporal.Duration(-1, 0, 0, -4); +assert.sameValue(d.toJSON(), "-P1Y4D", "negative years and days"); +d = new Temporal.Duration(0, 2, 0, 4); +assert.sameValue(d.toJSON(), "P2M4D", "positive months and days"); +d = new Temporal.Duration(0, -2, 0, -4); +assert.sameValue(d.toJSON(), "-P2M4D", "negative months and days"); +d = new Temporal.Duration(0, 0, 3, 4); +assert.sameValue(d.toJSON(), "P3W4D", "positive weeks and days"); +d = new Temporal.Duration(0, 0, -3, -4); +assert.sameValue(d.toJSON(), "-P3W4D", "negative weeks and days"); + +d = new Temporal.Duration(0, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "PT5H", "positive hours"); +d = new Temporal.Duration(0, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-PT5H", "negative hours"); +d = new Temporal.Duration(1, 0, 0, 0, 5); +assert.sameValue(d.toJSON(), "P1YT5H", "positive years and hours"); +d = new Temporal.Duration(-1, 0, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P1YT5H", "negative years and hours"); +d = new Temporal.Duration(0, 2, 0, 0, 5); +assert.sameValue(d.toJSON(), "P2MT5H", "positive months and hours"); +d = new Temporal.Duration(0, -2, 0, 0, -5); +assert.sameValue(d.toJSON(), "-P2MT5H", "negative months and hours"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 6); +assert.sameValue(d.toJSON(), "PT6M", "positive minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6); +assert.sameValue(d.toJSON(), "-PT6M", "negative minutes"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6); +assert.sameValue(d.toJSON(), "PT5H6M", "positive hours and minutes"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6); +assert.sameValue(d.toJSON(), "-PT5H6M", "negative hours and minutes"); +d = new Temporal.Duration(0, 0, 3, 0, 0, 6); +assert.sameValue(d.toJSON(), "P3WT6M", "positive weeks and minutes"); +d = new Temporal.Duration(0, 0, -3, 0, 0, -6); +assert.sameValue(d.toJSON(), "-P3WT6M", "negative weeks and minutes"); +d = new Temporal.Duration(0, 0, 0, 4, 0, 6); +assert.sameValue(d.toJSON(), "P4DT6M", "positive days and minutes"); +d = new Temporal.Duration(0, 0, 0, -4, 0, -6); +assert.sameValue(d.toJSON(), "-P4DT6M", "negative days and minutes"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 7); +assert.sameValue(d.toJSON(), "PT7S", "positive seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -7); +assert.sameValue(d.toJSON(), "-PT7S", "negative seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 0, 7); +assert.sameValue(d.toJSON(), "PT5H7S", "positive hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, 0, -7); +assert.sameValue(d.toJSON(), "-PT5H7S", "negative hours and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 6, 7); +assert.sameValue(d.toJSON(), "PT6M7S", "positive minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, -6, -7); +assert.sameValue(d.toJSON(), "-PT6M7S", "negative minutes and seconds"); +d = new Temporal.Duration(0, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "PT5H6M7S", "positive hours, minutes, seconds"); +d = new Temporal.Duration(0, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-PT5H6M7S", "negative hours, minutes, seconds"); +d = new Temporal.Duration(1, 0, 0, 0, 5, 6, 7); +assert.sameValue(d.toJSON(), "P1YT5H6M7S", "positive years, hours, minutes, seconds"); +d = new Temporal.Duration(-1, 0, 0, 0, -5, -6, -7); +assert.sameValue(d.toJSON(), "-P1YT5H6M7S", "negative years, hours, minutes, seconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 8); +assert.sameValue(d.toJSON(), "PT0.008S", "positive milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -8); +assert.sameValue(d.toJSON(), "-PT0.008S", "negative milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 80); +assert.sameValue(d.toJSON(), "PT0.08S", "positive milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -80); +assert.sameValue(d.toJSON(), "-PT0.08S", "negative milliseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 87); +assert.sameValue(d.toJSON(), "PT0.087S", "positive two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -87); +assert.sameValue(d.toJSON(), "-PT0.087S", "negative two-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876); +assert.sameValue(d.toJSON(), "PT0.876S", "positive three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876); +assert.sameValue(d.toJSON(), "-PT0.876S", "negative three-digit milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 876543); +assert.sameValue(d.toJSON(), "PT876.543S", "positive large milliseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -876543); +assert.sameValue(d.toJSON(), "-PT876.543S", "negative large milliseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 9); +assert.sameValue(d.toJSON(), "PT0.000009S", "positive microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -9); +assert.sameValue(d.toJSON(), "-PT0.000009S", "negative microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 90); +assert.sameValue(d.toJSON(), "PT0.00009S", "positive microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -90); +assert.sameValue(d.toJSON(), "-PT0.00009S", "negative microseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 98); +assert.sameValue(d.toJSON(), "PT0.000098S", "positive two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -98); +assert.sameValue(d.toJSON(), "-PT0.000098S", "negative two-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 900); +assert.sameValue(d.toJSON(), "PT0.0009S", "positive microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -900); +assert.sameValue(d.toJSON(), "-PT0.0009S", "negative microseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987); +assert.sameValue(d.toJSON(), "PT0.000987S", "positive three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987); +assert.sameValue(d.toJSON(), "-PT0.000987S", "negative three-digit microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654); +assert.sameValue(d.toJSON(), "PT0.987654S", "positive large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654); +assert.sameValue(d.toJSON(), "-PT0.987654S", "negative large microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 987654321); +assert.sameValue(d.toJSON(), "PT987.654321S", "positive larger microseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -987654321); +assert.sameValue(d.toJSON(), "-PT987.654321S", "negative larger microseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1); +assert.sameValue(d.toJSON(), "PT0.000000001S", "positive nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1); +assert.sameValue(d.toJSON(), "-PT0.000000001S", "negative nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 10); +assert.sameValue(d.toJSON(), "PT0.00000001S", "positive nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -10); +assert.sameValue(d.toJSON(), "-PT0.00000001S", "negative nanoseconds multiple of 10"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 12); +assert.sameValue(d.toJSON(), "PT0.000000012S", "positive two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -12); +assert.sameValue(d.toJSON(), "-PT0.000000012S", "negative two-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 100); +assert.sameValue(d.toJSON(), "PT0.0000001S", "positive nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -100); +assert.sameValue(d.toJSON(), "-PT0.0000001S", "negative nanoseconds multiple of 100"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123); +assert.sameValue(d.toJSON(), "PT0.000000123S", "positive three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123); +assert.sameValue(d.toJSON(), "-PT0.000000123S", "negative three-digit nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456); +assert.sameValue(d.toJSON(), "PT0.000123456S", "positive large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456); +assert.sameValue(d.toJSON(), "-PT0.000123456S", "negative large nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 123456789); +assert.sameValue(d.toJSON(), "PT0.123456789S", "positive larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -123456789); +assert.sameValue(d.toJSON(), "-PT0.123456789S", "negative larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 1234567891); +assert.sameValue(d.toJSON(), "PT1.234567891S", "positive even larger nanoseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -1234567891); +assert.sameValue(d.toJSON(), "-PT1.234567891S", "negative even larger nanoseconds"); + +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 1); +assert.sameValue(d.toJSON(), "PT4.003002001S", "positive seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -1); +assert.sameValue(d.toJSON(), "-PT4.003002001S", "negative seconds and subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90001); +assert.sameValue(d.toJSON(), "PT4.003092001S", "positive seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90001); +assert.sameValue(d.toJSON(), "-PT4.003092001S", "negative seconds and large subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 4, 3, 2, 90080001); +assert.sameValue(d.toJSON(), "PT4.093082001S", "positive seconds and larger subseconds"); +d = new Temporal.Duration(0, 0, 0, 0, 0, 0, -4, -3, -2, -90080001); +assert.sameValue(d.toJSON(), "-PT4.093082001S", "negative seconds and larger subseconds"); + +d = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 1); +assert.sameValue(d.toJSON(), "P1Y2M3W4DT5H6M7.008009001S", "all fields positive"); +d = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -1); +assert.sameValue(d.toJSON(), "-P1Y2M3W4DT5H6M7.008009001S", "all fields negative"); + +d = new Temporal.Duration(1234, 2345, 3456, 4567, 5678, 6789, 7890, 890, 901, 123); +assert.sameValue(d.toJSON(), "P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and positive"); +d = new Temporal.Duration(-1234, -2345, -3456, -4567, -5678, -6789, -7890, -890, -901, -123); +assert.sameValue(d.toJSON(), "-P1234Y2345M3456W4567DT5678H6789M7890.890901123S", "all fields large and negative"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-auto.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 00000000000..941b9dce931 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-auto.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.duration.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [Temporal] +---*/ + +const wholeSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7); +const subSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650); + +const tests = [ + [wholeSeconds, "P1Y2M3W4DT5H6M7S"], + [subSeconds, "P1Y2M3W4DT5H6M7.98765S"], +]; + +for (const [duration, expected] of tests) { + assert.sameValue(duration.toString(), expected, "default is to emit seconds and drop trailing zeroes"); + assert.sameValue(duration.toString({ fractionalSecondDigits: "auto" }), expected, "auto is the default"); +} diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js index 036b977ad16..5af9938e232 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-invalid-string.js @@ -16,6 +16,7 @@ features: [Temporal] const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); -for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos"]) { - assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos", "auto\0"]) { + assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); } diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-number.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 00000000000..764986cb2e4 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-number.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.duration.prototype.tostring +description: Number for fractionalSecondDigits option +features: [Temporal] +---*/ + +const wholeSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7); +const subSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650); + +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 0 }), "P1Y2M3W4DT5H6M7S", + "truncates 4 decimal places to 0"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 2 }), "P1Y2M3W4DT5H6M7.00S", + "pads whole seconds to 2 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 2 }), "P1Y2M3W4DT5H6M7.98S", + "truncates 4 decimal places to 2"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 3 }), "P1Y2M3W4DT5H6M7.987S", + "truncates 4 decimal places to 3"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 6 }), "P1Y2M3W4DT5H6M7.987650S", + "pads 4 decimal places to 6"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 7 }), "P1Y2M3W4DT5H6M7.0000000S", + "pads whole seconds to 7 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 7 }), "P1Y2M3W4DT5H6M7.9876500S", + "pads 4 decimal places to 7"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 9 }), "P1Y2M3W4DT5H6M7.987650000S", + "pads 4 decimal places to 9"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js index 9a20541c19f..ab73ad69bd1 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-out-of-range.js @@ -16,7 +16,11 @@ features: [Temporal] const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); -assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -Infinity })); -assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -1 })); -assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 10 })); -assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: Infinity })); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -Infinity }), + "−∞ is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: -1 }), + "−1 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 10 }), + "10 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: Infinity }), + "∞ is out of range for fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js index 2c3af23ae92..292b8df300a 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-undefined.js @@ -16,10 +16,21 @@ info: | features: [Temporal] ---*/ -const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); +const wholeSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7); +const subSeconds = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650); -const explicit = duration.toString({ fractionalSecondDigits: undefined }); -assert.sameValue(explicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto"); +const tests = [ + [wholeSeconds, "P1Y2M3W4DT5H6M7S"], + [subSeconds, "P1Y2M3W4DT5H6M7.98765S"], +]; -const implicit = duration.toString({}); -assert.sameValue(implicit, "P1Y2M3W4DT5H6M7.98765S", "default fractionalSecondDigits is auto"); +for (const [duration, expected] of tests) { + const explicit = duration.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); + + const implicit = duration.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); + + const lambda = duration.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); +} diff --git a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js index 143de7c3440..625daaff1da 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-wrong-type.js @@ -22,4 +22,26 @@ features: [Temporal] ---*/ const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 650, 0); -TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(duration); + +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: null }), + "null is not a number and converts to the string 'null' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: true }), + "true is not a number and converts to the string 'true' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: false }), + "false is not a number and converts to the string 'false' which is not valid for fractionalSecondDigits"); +assert.throws(TypeError, () => duration.toString({ fractionalSecondDigits: Symbol() }), + "symbols are not numbers and cannot convert to strings"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: 2n }), + "bigints are not numbers and convert to strings which are not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => duration.toString({ fractionalSecondDigits: {} }), + "plain objects are not numbers and convert to strings which are not valid for fractionalSecondDigits"); + +const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); +const result = duration.toString({ fractionalSecondDigits: observer }); +assert.sameValue(result, "P1Y2M3W4DT5H6M7.98765S", "object with toString uses toString return value"); +assert.compareArray(actual, expected, "object with toString calls toString and not valueOf"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..7cd68050a11 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/options-wrong-type.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.duration.prototype.tostring +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.Duration(0, 0, 0, 0, 1); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-ceil.js b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-ceil.js new file mode 100644 index 00000000000..cdef0c52741 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-ceil.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: ceil value for roundingMode option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 123, 987, 500); + +const result1 = duration.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); +assert.sameValue(result1, "P1Y2M3W4DT5H6M7.123988S", + "roundingMode is ceil (with 6 digits from smallestUnit)"); + +const result2 = duration.toString({ fractionalSecondDigits: 6, roundingMode: "ceil" }); +assert.sameValue(result2, "P1Y2M3W4DT5H6M7.123988S", + "roundingMode is ceil (with 6 digits from fractionalSecondDigits)"); + +const result3 = duration.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result3, "P1Y2M3W4DT5H6M7.124S", + "roundingMode is ceil (with 3 digits from smallestUnit)"); + +const result4 = duration.toString({ fractionalSecondDigits: 3, roundingMode: "ceil" }); +assert.sameValue(result4, "P1Y2M3W4DT5H6M7.124S", + "roundingMode is ceil (with 3 digits from fractionalSecondDigits)"); + +const result5 = duration.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result5, "P1Y2M3W4DT5H6M8S", + "roundingMode is ceil (with 0 digits from smallestUnit)"); + +const result6 = duration.toString({ fractionalSecondDigits: 0, roundingMode: "ceil" }); +assert.sameValue(result6, "P1Y2M3W4DT5H6M8S", + "roundingMode is ceil (with 0 digits from fractionalSecondDigits)"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-floor.js b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-floor.js new file mode 100644 index 00000000000..e1ee18b5c8e --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-floor.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: floor value for roundingMode option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 123, 987, 500); + +const result1 = duration.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); +assert.sameValue(result1, "P1Y2M3W4DT5H6M7.123987S", + "roundingMode is floor (with 6 digits from smallestUnit)"); + +const result2 = duration.toString({ fractionalSecondDigits: 6, roundingMode: "floor" }); +assert.sameValue(result2, "P1Y2M3W4DT5H6M7.123987S", + "roundingMode is floor (with 6 digits from fractionalSecondDigits)"); + +const result3 = duration.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result3, "P1Y2M3W4DT5H6M7.123S", + "roundingMode is floor (with 3 digits from smallestUnit)"); + +const result4 = duration.toString({ fractionalSecondDigits: 3, roundingMode: "floor" }); +assert.sameValue(result4, "P1Y2M3W4DT5H6M7.123S", + "roundingMode is floor (with 3 digits from fractionalSecondDigits)"); + +const result5 = duration.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result5, "P1Y2M3W4DT5H6M7S", + "roundingMode is floor (with 0 digits from smallestUnit)"); + +const result6 = duration.toString({ fractionalSecondDigits: 0, roundingMode: "floor" }); +assert.sameValue(result6, "P1Y2M3W4DT5H6M7S", + "roundingMode is floor (with 0 digits from fractionalSecondDigits)"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-halfExpand.js b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 00000000000..9a11468a126 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-halfExpand.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: halfExpand value for roundingMode option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 123, 987, 500); + +const result1 = duration.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); +assert.sameValue(result1, "P1Y2M3W4DT5H6M7.123988S", + "roundingMode is halfExpand (with 6 digits from smallestUnit)"); + +const result2 = duration.toString({ fractionalSecondDigits: 6, roundingMode: "halfExpand" }); +assert.sameValue(result2, "P1Y2M3W4DT5H6M7.123988S", + "roundingMode is halfExpand (with 6 digits from fractionalSecondDigits)"); + +const result3 = duration.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result3, "P1Y2M3W4DT5H6M7.124S", + "roundingMode is halfExpand (with 3 digits from smallestUnit)"); + +const result4 = duration.toString({ fractionalSecondDigits: 3, roundingMode: "halfExpand" }); +assert.sameValue(result4, "P1Y2M3W4DT5H6M7.124S", + "roundingMode is halfExpand (with 3 digits from fractionalSecondDigits)"); + +const result5 = duration.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result5, "P1Y2M3W4DT5H6M7S", + "roundingMode is halfExpand (with 0 digits from smallestUnit)"); + +const result6 = duration.toString({ fractionalSecondDigits: 0, roundingMode: "halfExpand" }); +assert.sameValue(result6, "P1Y2M3W4DT5H6M7S", + "roundingMode is halfExpand (with 0 digits from fractionalSecondDigits)"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-trunc.js b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-trunc.js new file mode 100644 index 00000000000..3b66fb5201a --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/roundingmode-trunc.js @@ -0,0 +1,34 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.tostring +description: trunc value for roundingMode option +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 123, 987, 500); + +const result1 = duration.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); +assert.sameValue(result1, "P1Y2M3W4DT5H6M7.123987S", + "roundingMode is trunc (with 6 digits from smallestUnit)"); + +const result2 = duration.toString({ fractionalSecondDigits: 6, roundingMode: "trunc" }); +assert.sameValue(result2, "P1Y2M3W4DT5H6M7.123987S", + "roundingMode is trunc (with 6 digits from fractionalSecondDigits)"); + +const result3 = duration.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result3, "P1Y2M3W4DT5H6M7.123S", + "roundingMode is trunc (with 3 digits from smallestUnit)"); + +const result4 = duration.toString({ fractionalSecondDigits: 3, roundingMode: "trunc" }); +assert.sameValue(result4, "P1Y2M3W4DT5H6M7.123S", + "roundingMode is trunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = duration.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result5, "P1Y2M3W4DT5H6M7S", + "roundingMode is trunc (with 0 digits from smallestUnit)"); + +const result6 = duration.toString({ fractionalSecondDigits: 0, roundingMode: "trunc" }); +assert.sameValue(result6, "P1Y2M3W4DT5H6M7S", + "roundingMode is trunc (with 0 digits from fractionalSecondDigits)"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-fractionalseconddigits.js b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 00000000000..19d10523801 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-fractionalseconddigits.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.duration.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 789, 999, 999); +const tests = [ + ["second", "P1Y2M3W4DT5H6M7S"], + ["millisecond", "P1Y2M3W4DT5H6M7.789S"], + ["microsecond", "P1Y2M3W4DT5H6M7.789999S"], + ["nanosecond", "P1Y2M3W4DT5H6M7.789999999S"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = duration.toString({ + smallestUnit, + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } + }); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); +} + +assert.throws(RangeError, () => duration.toString({ + smallestUnit: "hour", + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js index 046b4a99f70..5405996c5df 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-invalid-string.js @@ -8,7 +8,32 @@ features: [Temporal] ---*/ const duration = new Temporal.Duration(0, 0, 0, 0, 12, 34, 56, 123, 987, 500); -const values = ["eras", "years", "months", "weeks", "days", "hours", "minutes", "nonsense", "other string", "mill\u0131seconds", "SECONDS"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => duration.toString({ smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "hour", + "minute", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => duration.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js index fce836b31b1..24880177e23 100644 --- a/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js +++ b/test/built-ins/Temporal/Duration/prototype/toString/smallestunit-valid-units.js @@ -9,12 +9,37 @@ features: [Temporal] const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321); -assert.sameValue(duration.toString({ smallestUnit: "second" }), "P1Y2M3W4DT5H6M7S"); -assert.sameValue(duration.toString({ smallestUnit: "millisecond" }), "P1Y2M3W4DT5H6M7.987S"); -assert.sameValue(duration.toString({ smallestUnit: "microsecond" }), "P1Y2M3W4DT5H6M7.987654S"); -assert.sameValue(duration.toString({ smallestUnit: "nanosecond" }), "P1Y2M3W4DT5H6M7.987654321S"); +function test(instance, expectations, description) { + for (const [smallestUnit, expectedResult] of expectations) { + assert.sameValue(instance.toString({ smallestUnit }), expectedResult, + `${description} with smallestUnit "${smallestUnit}"`); + } +} + +test( + duration, + [ + ["seconds", "P1Y2M3W4DT5H6M7S"], + ["milliseconds", "P1Y2M3W4DT5H6M7.987S"], + ["microseconds", "P1Y2M3W4DT5H6M7.987654S"], + ["nanoseconds", "P1Y2M3W4DT5H6M7.987654321S"], + ], + "subseconds toString" +); + +test( + new Temporal.Duration(1, 2, 3, 4, 5, 6, 7), + [ + ["seconds", "P1Y2M3W4DT5H6M7S"], + ["milliseconds", "P1Y2M3W4DT5H6M7.000S"], + ["microseconds", "P1Y2M3W4DT5H6M7.000000S"], + ["nanoseconds", "P1Y2M3W4DT5H6M7.000000000S"], + ], + "whole seconds toString" +); const notValid = [ + "era", "year", "month", "week", @@ -24,5 +49,6 @@ const notValid = [ ]; notValid.forEach((smallestUnit) => { - assert.throws(RangeError, () => duration.toString({ smallestUnit }), smallestUnit); + assert.throws(RangeError, () => duration.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); }); diff --git a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 00000000000..6ae88e1d942 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,49 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Total of a calendar unit where larger calendar units have to be converted +// down, to cover the path that goes through UnbalanceDurationRelative +// The calls come from these paths: +// Duration.total() -> +// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() (3x) +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); +instance1.total({ unit: "days", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 8, "converting larger calendar units down"); + +// Total of a calendar unit where smaller calendar units have to be converted +// up, to cover the path that goes through MoveRelativeZonedDateTime +// The calls come from these paths: +// Duration.total() -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// BalanceDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +const instance2 = new Temporal.Duration(0, 0, 1, 1); +instance2.total({ unit: "weeks", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 6, "converting smaller calendar units up"); diff --git a/test/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js index 9b92bca4836..ae20fe1b49e 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js +++ b/test/built-ins/Temporal/Duration/prototype/total/options-wrong-type.js @@ -1,13 +1,13 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// Copyright (C) 2022 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.duration.prototype.total -description: TypeError thrown when options argument is missing or a primitive +description: TypeError thrown when options argument is missing or a non-string primitive features: [BigInt, Symbol, Temporal] ---*/ -const values = [ +const badOptions = [ undefined, null, true, @@ -17,7 +17,8 @@ const values = [ ]; const instance = new Temporal.Duration(0, 0, 0, 0, 1); -assert.throws(TypeError, () => instance.total(), "TypeError on missing argument"); -values.forEach((value) => { - assert.throws(TypeError, () => instance.total(value), `TypeError on wrong argument type ${typeof(value)}`); -}); +assert.throws(TypeError, () => instance.total(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.total(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Duration/prototype/with/all-negative.js b/test/built-ins/Temporal/Duration/prototype/with/all-negative.js new file mode 100644 index 00000000000..e094455bb8e --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/all-negative.js @@ -0,0 +1,93 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all negative values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllNegative = { + years: -9, + months: -8, + weeks: -7, + days: -6, + hours: -5, + minutes: -4, + seconds: -3, + milliseconds: -2, + microseconds: -1, + nanoseconds: -10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all zeroes with all negative" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive with all negative" +); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all positive large numbers with all negative" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllNegative), -9, -8, -7, -6, -5, -4, -3, -2, -1, -10, + "replace all negative with all negative" +); diff --git a/test/built-ins/Temporal/Duration/prototype/with/all-positive.js b/test/built-ins/Temporal/Duration/prototype/with/all-positive.js new file mode 100644 index 00000000000..21584232fc0 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/all-positive.js @@ -0,0 +1,92 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces the fields with + all positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const argAllPositive = { + years: 9, + months: 8, + weeks: 7, + days: 6, + hours: 5, + minutes: 4, + seconds: 3, + milliseconds: 2, + microseconds: 1, + nanoseconds: 10, +}; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all zeroes with all positive" +); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive with all positive"); + +const d3 = new Temporal.Duration(1e5, 2e5, 3e5, 4e5, 5e5, 6e5, 7e5, 8e5, 9e5, 10e5); +TemporalHelpers.assertDuration( + d3.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all positive large numbers with all positive" +); + +const d4 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +TemporalHelpers.assertDuration( + d4.with(argAllPositive), 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, + "replace all negative with all positive" +); diff --git a/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js b/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js new file mode 100644 index 00000000000..5c17076bec5 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/argument-object-wrong-shape.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + The durationLike argument must contain at least one correctly spelled property +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + {}, + [], + () => {}, + // objects with only singular keys (plural is the correct spelling) + { year: 1 }, + { month: 2 }, + { week: 3 }, + { day: 4 }, + { hour: 5 }, + { minute: 6 }, + { second: 7 }, + { millisecond: 8 }, + { microsecond: 9 }, + { nanosecond: 10 }, +].forEach((badObject) => { + assert.throws(TypeError, () => d.with(badObject), + "Throw TypeError if temporalDurationLike is not valid"); +}); diff --git a/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js b/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js new file mode 100644 index 00000000000..41163a35da6 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/argument-wrong-type.js @@ -0,0 +1,27 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw TypeError if the temporalDurationLike argument is the wrong type +features: [Temporal] +---*/ + +let d = new Temporal.Duration(1, 2, 3, 4, 5); + +[ + "string", + "P1YT1M", + true, + false, + NaN, + Infinity, + undefined, + null, + 123, + Symbol(), + 456n, +].forEach((badInput) => { + assert.throws(TypeError, () => d.with(badInput), + "Throw TypeError if temporalDurationLike is not valid"); +}); diff --git a/test/built-ins/Temporal/Duration/prototype/with/branding.js b/test/built-ins/Temporal/Duration/prototype/with/branding.js index 2bc9af85bf8..b04b2fefd60 100644 --- a/test/built-ins/Temporal/Duration/prototype/with/branding.js +++ b/test/built-ins/Temporal/Duration/prototype/with/branding.js @@ -11,12 +11,14 @@ const with_ = Temporal.Duration.prototype.with; assert.sameValue(typeof with_, "function"); -assert.throws(TypeError, () => with_.call(undefined), "undefined"); -assert.throws(TypeError, () => with_.call(null), "null"); -assert.throws(TypeError, () => with_.call(true), "true"); -assert.throws(TypeError, () => with_.call(""), "empty string"); -assert.throws(TypeError, () => with_.call(Symbol()), "symbol"); -assert.throws(TypeError, () => with_.call(1), "1"); -assert.throws(TypeError, () => with_.call({}), "plain object"); -assert.throws(TypeError, () => with_.call(Temporal.Duration), "Temporal.Duration"); -assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype), "Temporal.Duration.prototype"); +const arg = { years: 3 }; + +assert.throws(TypeError, () => with_.call(undefined, arg), "undefined"); +assert.throws(TypeError, () => with_.call(null, arg), "null"); +assert.throws(TypeError, () => with_.call(true, arg), "true"); +assert.throws(TypeError, () => with_.call("", arg), "empty string"); +assert.throws(TypeError, () => with_.call(Symbol(), arg), "symbol"); +assert.throws(TypeError, () => with_.call(1, arg), "1"); +assert.throws(TypeError, () => with_.call({}, arg), "plain object"); +assert.throws(TypeError, () => with_.call(Temporal.Duration, arg), "Temporal.Duration"); +assert.throws(TypeError, () => with_.call(Temporal.Duration.prototype, arg), "Temporal.Duration.prototype"); diff --git a/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js b/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js new file mode 100644 index 00000000000..b1425de497f --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/partial-positive.js @@ -0,0 +1,86 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: > + Returns a correctly merged object when the argument replaces only some of the + fields with positive values. +info: | + 1. Let duration be the this value. + 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]). + 3. Let temporalDurationLike be ? ToPartialDuration(temporalDurationLike). + 4. If temporalDurationLike.[[Years]] is not undefined, then + a. Let years be temporalDurationLike.[[Years]]. + 5. Else, + a. Let years be duration.[[Years]]. + 6. If temporalDurationLike.[[Months]] is not undefined, then + a. Let months be temporalDurationLike.[[Months]]. + 7. Else, + a. Let months be duration.[[Months]]. + 8. If temporalDurationLike.[[Weeks]] is not undefined, then + a. Let weeks be temporalDurationLike.[[Weeks]]. + 9. Else, + a. Let weeks be duration.[[Weeks]]. + 10. If temporalDurationLike.[[Days]] is not undefined, then + a. Let days be temporalDurationLike.[[Days]]. + 11. Else, + a. Let days be duration.[[Days]]. + 12. If temporalDurationLike.[[Hours]] is not undefined, then + a. Let hours be temporalDurationLike.[[Hours]]. + 13. Else, + a. Let hours be duration.[[Hours]]. + 14. If temporalDurationLike.[[Minutes]] is not undefined, then + a. Let minutes be temporalDurationLike.[[Minutes]]. + 15. Else, + a. Let minutes be duration.[[Minutes]]. + 16. If temporalDurationLike.[[Seconds]] is not undefined, then + a. Let seconds be temporalDurationLike.[[Seconds]]. + 17. Else, + a. Let seconds be duration.[[Seconds]]. + 18. If temporalDurationLike.[[Milliseconds]] is not undefined, then + a. Let milliseconds be temporalDurationLike.[[Milliseconds]]. + 19. Else, + a. Let milliseconds be duration.[[Milliseconds]]. + 20. If temporalDurationLike.[[Microseconds]] is not undefined, then + a. Let microseconds be temporalDurationLike.[[Microseconds]]. + 21. Else, + a. Let microseconds be duration.[[Microseconds]]. + 22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then + a. Let nanoseconds be temporalDurationLike.[[Nanoseconds]]. + 23. Else, + a. Let nanoseconds be duration.[[Nanoseconds]]. + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const durationlike1 = { years: 9, hours: 5 }; +const durationlike2 = { months: 8, minutes: 4 }; +const durationlike3 = { weeks: 7, seconds: 3 }; +const durationlike4 = { days: 6, milliseconds: 2 }; +const durationlike5 = { microseconds: 987, nanoseconds: 123 }; + +const d1 = new Temporal.Duration(); +TemporalHelpers.assertDuration( + d1.with(durationlike1), 9, 0, 0, 0, 5, 0, 0, 0, 0, 0, "replace all zeroes with years and hours"); +TemporalHelpers.assertDuration( + d1.with(durationlike2), 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, "replace all zeroes wtih months and minutes"); +TemporalHelpers.assertDuration( + d1.with(durationlike3), 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, "replace all zeroes with weeks and seconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike4), 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, "replace all zeroes with days and milliseconds"); +TemporalHelpers.assertDuration( + d1.with(durationlike5), 0, 0, 0, 0, 0, 0, 0, 0, 987, 123, "replace all zeroes with microseconds and nanoseconds"); + +const d2 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +TemporalHelpers.assertDuration( + d2.with(durationlike1), 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, "replace all positive with years and hours"); +TemporalHelpers.assertDuration( + d2.with(durationlike2), 1, 8, 3, 4, 5, 4, 7, 8, 9, 10, "replace all positive with months and minutes"); +TemporalHelpers.assertDuration( + d2.with(durationlike3), 1, 2, 7, 4, 5, 6, 3, 8, 9, 10, "replace all positive with weeks and seconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike4), 1, 2, 3, 6, 5, 6, 7, 2, 9, 10, "replace all positive with days and milliseconds"); +TemporalHelpers.assertDuration( + d2.with(durationlike5), 1, 2, 3, 4, 5, 6, 7, 8, 987, 123, "replace all positive with microseconds and nanoseconds"); diff --git a/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js b/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js new file mode 100644 index 00000000000..239951b34d1 --- /dev/null +++ b/test/built-ins/Temporal/Duration/prototype/with/sign-conflict-throws-rangeerror.js @@ -0,0 +1,28 @@ +// Copyright (C) 2021 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.with +description: Throw RangeError if the resulting duration has mixed signs +info: | + 24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds). +features: [Temporal] +---*/ + +const d1 = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); +const d2 = new Temporal.Duration(-1, -2, -3, -4, -5, -6, -7, -8, -9, -10); +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +fields.forEach((field) => { + assert.throws( + RangeError, + () => d1.with({ [field]: -1 }), + `sign in argument { ${field}: -1 } conflicting with sign of duration should throw RangeError` + ); + + assert.throws( + RangeError, + () => d2.with({ [field]: 1 }), + `sign in argument { ${field}: 1 } conflicting with sign of duration should throw RangeError` + ); +}); diff --git a/test/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js b/test/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js index 51cba2ff1a1..0cd3a0a985e 100644 --- a/test/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js +++ b/test/built-ins/Temporal/Instant/prototype/round/options-wrong-type.js @@ -1,13 +1,13 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// Copyright (C) 2022 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.instant.prototype.round -description: TypeError thrown when options argument is missing or a primitive -features: [Symbol, Temporal] +description: TypeError thrown when options argument is missing or a non-string primitive +features: [BigInt, Symbol, Temporal] ---*/ -const values = [ +const badOptions = [ undefined, null, true, @@ -17,7 +17,8 @@ const values = [ ]; const instance = new Temporal.Instant(0n); -assert.throws(TypeError, () => instance.round(), "missing argument"); -for (const value of values) { - assert.throws(TypeError, () => instance.round(value), `argument ${String(value)}`); -} +assert.throws(TypeError, () => instance.round(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.round(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Instant/prototype/round/rounding-direction.js b/test/built-ins/Temporal/Instant/prototype/round/rounding-direction.js new file mode 100644 index 00000000000..88a6abba4c2 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/round/rounding-direction.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.round +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(-65_261_246_399_500_000_000n); // -000099-12-15T12:00:00.5Z +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "floor" }).epochNanoseconds, + -65_261_246_400_000_000_000n, // -000099-12-15T12:00:00Z + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode floor)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "trunc" }).epochNanoseconds, + -65_261_246_400_000_000_000n, // -000099-12-15T12:00:00Z + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "ceil" }).epochNanoseconds, + -65_261_246_399_000_000_000n, // -000099-12-15T12:00:01Z + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "halfExpand" }).epochNanoseconds, + -65_261_246_399_000_000_000n, // -000099-12-15T12:00:01Z + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js index 298c3ce64d6..37560379091 100644 --- a/test/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/round/smallestunit-invalid-string.js @@ -8,4 +8,28 @@ features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_123_987_500n); -assert.throws(RangeError, () => instant.round({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => instant.round({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js index 57aa9977ef2..48befae1256 100644 --- a/test/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); const later = new Temporal.Instant(1_000_090_061_987_654_321n); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/Instant/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/Instant/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..52978927974 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/since/options-wrong-type.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.instant.prototype.since +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.Instant(0n); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.Instant(3600_000_000_000n), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js index 0e91f3e745d..25f795a89ae 100644 --- a/test/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); const later = new Temporal.Instant(1_000_090_061_987_654_321n); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/Instant/prototype/toJSON/year-format.js b/test/built-ins/Temporal/Instant/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..01ffe822c86 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toJSON/year-format.js @@ -0,0 +1,53 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +let instance = new Temporal.Instant(epochNsInYear(-100000n)); +assert.sameValue(instance.toJSON(), "-100000-07-01T21:30:36Z", "large negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-10000n)); +assert.sameValue(instance.toJSON(), "-010000-07-01T21:30:36Z", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-9999n)); +assert.sameValue(instance.toJSON(), "-009999-07-02T03:19:48Z", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1000n)); +assert.sameValue(instance.toJSON(), "-001000-07-02T09:30:36Z", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-999n)); +assert.sameValue(instance.toJSON(), "-000999-07-02T15:19:48Z", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1n)); +assert.sameValue(instance.toJSON(), "-000001-07-02T15:41:24Z", "year -1 formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(0n)); +assert.sameValue(instance.toJSON(), "0000-07-01T21:30:36Z", "year 0 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1n)); +assert.sameValue(instance.toJSON(), "0001-07-02T03:19:48Z", "year 1 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(999n)); +assert.sameValue(instance.toJSON(), "0999-07-02T03:41:24Z", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1000n)); +assert.sameValue(instance.toJSON(), "1000-07-02T09:30:36Z", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(9999n)); +assert.sameValue(instance.toJSON(), "9999-07-02T15:41:24Z", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(10000n)); +assert.sameValue(instance.toJSON(), "+010000-07-01T21:30:36Z", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(100000n)); +assert.sameValue(instance.toJSON(), "+100000-07-01T21:30:36Z", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-auto.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 00000000000..5e37b7ffd5c --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-auto.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.instant.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [BigInt, Temporal] +---*/ + +const zeroSeconds = new Temporal.Instant(0n); +const wholeSeconds = new Temporal.Instant(30_000_000_000n); +const subSeconds = new Temporal.Instant(30_123_400_000n); + +const tests = [ + [zeroSeconds, "1970-01-01T00:00:00Z"], + [wholeSeconds, "1970-01-01T00:00:30Z"], + [subSeconds, "1970-01-01T00:00:30.1234Z"], +]; + +for (const [instant, expected] of tests) { + assert.sameValue(instant.toString(), expected, "default is to emit seconds and drop trailing zeroes"); + assert.sameValue(instant.toString({ fractionalSecondDigits: "auto" }), expected, "auto is the default"); +} diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js index f75db5a7ffc..0a1cc3e3cb8 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-invalid-string.js @@ -10,10 +10,13 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.instant.prototype.tostring step 6: - 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_987_650_000n); -assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: "other string" })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos", "auto\0"]) { + assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); +} diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js index beb567b6889..1a3479b5cc6 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-non-integer.js @@ -10,7 +10,7 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.instant.prototype.tostring step 6: - 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-number.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 00000000000..e6ba9634053 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-number.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.instant.prototype.tostring +description: Number for fractionalSecondDigits option +features: [BigInt, Temporal] +---*/ + +const zeroSeconds = new Temporal.Instant(0n); +const wholeSeconds = new Temporal.Instant(30_000_000_000n); +const subSeconds = new Temporal.Instant(30_123_400_000n); + +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 0 }), "1970-01-01T00:00:30Z", + "truncates 4 decimal places to 0"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:00.00Z", + "pads zero seconds to 2 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:30.00Z", + "pads whole seconds to 2 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:30.12Z", + "truncates 4 decimal places to 2"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 3 }), "1970-01-01T00:00:30.123Z", + "truncates 4 decimal places to 3"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 6 }), "1970-01-01T00:00:30.123400Z", + "pads 4 decimal places to 6"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:00.0000000Z", + "pads zero seconds to 7 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:30.0000000Z", + "pads whole seconds to 7 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:30.1234000Z", + "pads 4 decimal places to 7"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 9 }), "1970-01-01T00:00:30.123400000Z", + "pads 4 decimal places to 9"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js index 4506d3ef215..a634aee8903 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-out-of-range.js @@ -10,13 +10,17 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.instant.prototype.tostring step 6: - 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_987_650_000n); -assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -1 })); -assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: 10 })); -assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -Infinity })); -assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: Infinity })); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -Infinity }), + "−∞ is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: -1 }), + "−1 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: 10 }), + "10 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: Infinity }), + "∞ is out of range for fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js index 7bed467685f..be0fbf77e38 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-undefined.js @@ -8,18 +8,31 @@ info: | sec-getoption step 3: 3. If _value_ is *undefined*, return _fallback_. sec-getstringornumberoption step 2: - 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.instant.prototype.tostring step 6: - 6. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 6. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ -const instant = new Temporal.Instant(1_000_000_000_987_650_000n); +const zeroSeconds = new Temporal.Instant(0n); +const wholeSeconds = new Temporal.Instant(30_000_000_000n); +const subSeconds = new Temporal.Instant(30_123_400_000n); -const explicit = instant.toString({ fractionalSecondDigits: undefined }); -assert.sameValue(explicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto"); +const tests = [ + [zeroSeconds, "1970-01-01T00:00:00Z"], + [wholeSeconds, "1970-01-01T00:00:30Z"], + [subSeconds, "1970-01-01T00:00:30.1234Z"], +]; -const implicit = instant.toString({}); -assert.sameValue(implicit, "2001-09-09T01:46:40.98765Z", "default fractionalSecondDigits is auto"); +for (const [instant, expected] of tests) { + const explicit = instant.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); + + const implicit = instant.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); + + const lambda = instant.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); +} diff --git a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js index 26eb23a3037..419b4a86d16 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/fractionalseconddigits-wrong-type.js @@ -22,4 +22,26 @@ features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_987_650_000n); -TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(instant); + +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: null }), + "null is not a number and converts to the string 'null' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: true }), + "true is not a number and converts to the string 'true' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: false }), + "false is not a number and converts to the string 'false' which is not valid for fractionalSecondDigits"); +assert.throws(TypeError, () => instant.toString({ fractionalSecondDigits: Symbol() }), + "symbols are not numbers and cannot convert to strings"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: 2n }), + "bigints are not numbers and convert to strings which are not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => instant.toString({ fractionalSecondDigits: {} }), + "plain objects are not numbers and convert to strings which are not valid for fractionalSecondDigits"); + +const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); +const result = instant.toString({ fractionalSecondDigits: observer }); +assert.sameValue(result, "2001-09-09T01:46:40.98765Z", "object with toString uses toString return value"); +assert.compareArray(actual, expected, "object with toString calls toString and not valueOf"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/Instant/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..4da3c9ebbc1 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/options-wrong-type.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.instant.prototype.tostring +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.Instant(0n); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Instant/prototype/toString/rounding-cross-midnight.js b/test/built-ins/Temporal/Instant/prototype/toString/rounding-cross-midnight.js new file mode 100644 index 00000000000..923671d4898 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/rounding-cross-midnight.js @@ -0,0 +1,13 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Rounding can cross midnight +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(946_684_799_999_999_999n); // one nanosecond before 2000-01-01T00:00:00 +for (const roundingMode of ["ceil", "halfExpand"]) { + assert.sameValue(instant.toString({ fractionalSecondDigits: 8, roundingMode }), "2000-01-01T00:00:00.00000000Z"); +} diff --git a/test/built-ins/Temporal/Instant/prototype/toString/rounding-direction.js b/test/built-ins/Temporal/Instant/prototype/toString/rounding-direction.js new file mode 100644 index 00000000000..f5185d9331d --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/rounding-direction.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +features: [Temporal] +---*/ + +const instance = new Temporal.Instant(-65_261_246_399_500_000_000n); // -000099-12-15T12:00:00.5Z +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "floor" }), + "-000099-12-15T12:00:00Z", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "trunc" }), + "-000099-12-15T12:00:00Z", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "ceil" }), + "-000099-12-15T12:00:01Z", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "halfExpand" }), + "-000099-12-15T12:00:01Z", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-ceil.js b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-ceil.js new file mode 100644 index 00000000000..f4cd9f0a802 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-ceil.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.instant.prototype.tostring +description: ceil value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const result1 = instant.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123988Z", + "roundingMode is ceil (with 6 digits from smallestUnit)"); + +const result2 = instant.toString({ fractionalSecondDigits: 6, roundingMode: "ceil" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123988Z", + "roundingMode is ceil (with 6 digits from fractionalSecondDigits)"); + +const result3 = instant.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result3, "2001-09-09T01:46:40.124Z", + "roundingMode is ceil (with 3 digits from smallestUnit)"); + +const result4 = instant.toString({ fractionalSecondDigits: 3, roundingMode: "ceil" }); +assert.sameValue(result4, "2001-09-09T01:46:40.124Z", + "roundingMode is ceil (with 3 digits from fractionalSecondDigits)"); + +const result5 = instant.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result5, "2001-09-09T01:46:41Z", + "roundingMode is ceil (with 0 digits from smallestUnit)"); + +const result6 = instant.toString({ fractionalSecondDigits: 0, roundingMode: "ceil" }); +assert.sameValue(result6, "2001-09-09T01:46:41Z", + "roundingMode is ceil (with 0 digits from fractionalSecondDigits)"); + +const result7 = instant.toString({ smallestUnit: "minute", roundingMode: "ceil" }); +assert.sameValue(result7, "2001-09-09T01:47Z", "roundingMode is ceil (round to minute)"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-floor.js b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-floor.js new file mode 100644 index 00000000000..d50326568b0 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-floor.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.instant.prototype.tostring +description: floor value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const result1 = instant.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123987Z", + "roundingMode is floor (with 6 digits from smallestUnit)"); + +const result2 = instant.toString({ fractionalSecondDigits: 6, roundingMode: "floor" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123987Z", + "roundingMode is floor (with 6 digits from fractionalSecondDigits)"); + +const result3 = instant.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result3, "2001-09-09T01:46:40.123Z", + "roundingMode is floor (with 3 digits from smallestUnit)"); + +const result4 = instant.toString({ fractionalSecondDigits: 3, roundingMode: "floor" }); +assert.sameValue(result4, "2001-09-09T01:46:40.123Z", + "roundingMode is floor (with 3 digits from fractionalSecondDigits)"); + +const result5 = instant.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result5, "2001-09-09T01:46:40Z", + "roundingMode is floor (with 0 digits from smallestUnit)"); + +const result6 = instant.toString({ fractionalSecondDigits: 0, roundingMode: "floor" }); +assert.sameValue(result6, "2001-09-09T01:46:40Z", + "roundingMode is floor (with 0 digits from fractionalSecondDigits)"); + +const result7 = instant.toString({ smallestUnit: "minute", roundingMode: "floor" }); +assert.sameValue(result7, "2001-09-09T01:46Z", "roundingMode is floor (round to minute)"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-halfExpand.js b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 00000000000..7b8aa7e8fa7 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-halfExpand.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.instant.prototype.tostring +description: halfExpand value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const result1 = instant.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123988Z", + "roundingMode is halfExpand (with 6 digits from smallestUnit)"); + +const result2 = instant.toString({ fractionalSecondDigits: 6, roundingMode: "halfExpand" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123988Z", + "roundingMode is halfExpand (with 6 digits from fractionalSecondDigits)"); + +const result3 = instant.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result3, "2001-09-09T01:46:40.124Z", + "roundingMode is halfExpand (with 3 digits from smallestUnit)"); + +const result4 = instant.toString({ fractionalSecondDigits: 3, roundingMode: "halfExpand" }); +assert.sameValue(result4, "2001-09-09T01:46:40.124Z", + "roundingMode is halfExpand (with 3 digits from fractionalSecondDigits)"); + +const result5 = instant.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result5, "2001-09-09T01:46:40Z", + "roundingMode is halfExpand (with 0 digits from smallestUnit)"); + +const result6 = instant.toString({ fractionalSecondDigits: 0, roundingMode: "halfExpand" }); +assert.sameValue(result6, "2001-09-09T01:46:40Z", + "roundingMode is halfExpand (with 0 digits from fractionalSecondDigits)"); + +const result7 = instant.toString({ smallestUnit: "minute", roundingMode: "halfExpand" }); +assert.sameValue(result7, "2001-09-09T01:47Z", "roundingMode is halfExpand (round to minute)"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-trunc.js b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-trunc.js new file mode 100644 index 00000000000..944c479c161 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/roundingmode-trunc.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.instant.prototype.tostring +description: trunc value for roundingMode option +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(1_000_000_000_123_987_500n); + +const result1 = instant.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123987Z", + "roundingMode is trunc (with 6 digits from smallestUnit)"); + +const result2 = instant.toString({ fractionalSecondDigits: 6, roundingMode: "trunc" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123987Z", + "roundingMode is trunc (with 6 digits from fractionalSecondDigits)"); + +const result3 = instant.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result3, "2001-09-09T01:46:40.123Z", + "roundingMode is trunc (with 3 digits from smallestUnit)"); + +const result4 = instant.toString({ fractionalSecondDigits: 3, roundingMode: "trunc" }); +assert.sameValue(result4, "2001-09-09T01:46:40.123Z", + "roundingMode is trunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = instant.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result5, "2001-09-09T01:46:40Z", + "roundingMode is trunc (with 0 digits from smallestUnit)"); + +const result6 = instant.toString({ fractionalSecondDigits: 0, roundingMode: "trunc" }); +assert.sameValue(result6, "2001-09-09T01:46:40Z", + "roundingMode is trunc (with 0 digits from fractionalSecondDigits)"); + +const result7 = instant.toString({ smallestUnit: "minute", roundingMode: "trunc" }); +assert.sameValue(result7, "2001-09-09T01:46Z", "roundingMode is trunc (round to minute)"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-fractionalseconddigits.js b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 00000000000..73d8f9aaf90 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-fractionalseconddigits.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const instant = new Temporal.Instant(56_789_999_999n); +const tests = [ + ["minute", "1970-01-01T00:00Z"], + ["second", "1970-01-01T00:00:56Z"], + ["millisecond", "1970-01-01T00:00:56.789Z"], + ["microsecond", "1970-01-01T00:00:56.789999Z"], + ["nanosecond", "1970-01-01T00:00:56.789999999Z"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = instant.toString({ + smallestUnit, + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } + }); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); +} + +assert.throws(RangeError, () => instant.toString({ + smallestUnit: "hour", + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js index f6ba6e30cc6..10b0b72baab 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-invalid-string.js @@ -8,4 +8,30 @@ features: [Temporal] ---*/ const instant = new Temporal.Instant(1_000_000_000_123_987_500n); -assert.throws(RangeError, () => instant.toString({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "hour", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "hours", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => instant.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js index 191eec97ed4..e1c53c93eb6 100644 --- a/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js +++ b/test/built-ins/Temporal/Instant/prototype/toString/smallestunit-valid-units.js @@ -9,11 +9,36 @@ features: [Temporal] const instant = new Temporal.Instant(1_000_000_000_123_456_789n); -assert.sameValue(instant.toString({ smallestUnit: "minute" }), "2001-09-09T01:46Z"); -assert.sameValue(instant.toString({ smallestUnit: "second" }), "2001-09-09T01:46:40Z"); -assert.sameValue(instant.toString({ smallestUnit: "millisecond" }), "2001-09-09T01:46:40.123Z"); -assert.sameValue(instant.toString({ smallestUnit: "microsecond" }), "2001-09-09T01:46:40.123456Z"); -assert.sameValue(instant.toString({ smallestUnit: "nanosecond" }), "2001-09-09T01:46:40.123456789Z"); +function test(instance, expectations, description) { + for (const [smallestUnit, expectedResult] of expectations) { + assert.sameValue(instance.toString({ smallestUnit }), expectedResult, + `${description} with smallestUnit "${smallestUnit}"`); + } +} + +test( + instant, + [ + ["minute", "2001-09-09T01:46Z"], + ["second", "2001-09-09T01:46:40Z"], + ["millisecond", "2001-09-09T01:46:40.123Z"], + ["microsecond", "2001-09-09T01:46:40.123456Z"], + ["nanosecond", "2001-09-09T01:46:40.123456789Z"], + ], + "subseconds toString" +); + +test( + new Temporal.Instant(999_999_960_000_000_000n), + [ + ["minute", "2001-09-09T01:46Z"], + ["second", "2001-09-09T01:46:00Z"], + ["millisecond", "2001-09-09T01:46:00.000Z"], + ["microsecond", "2001-09-09T01:46:00.000000Z"], + ["nanosecond", "2001-09-09T01:46:00.000000000Z"], + ], + "whole minutes toString" +); const notValid = [ "era", @@ -25,5 +50,6 @@ const notValid = [ ]; notValid.forEach((smallestUnit) => { - assert.throws(RangeError, () => instant.toString({ smallestUnit }), smallestUnit); + assert.throws(RangeError, () => instant.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); }); diff --git a/test/built-ins/Temporal/Instant/prototype/toString/year-format.js b/test/built-ins/Temporal/Instant/prototype/toString/year-format.js new file mode 100644 index 00000000000..195115a0c3f --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/toString/year-format.js @@ -0,0 +1,53 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +let instance = new Temporal.Instant(epochNsInYear(-100000n)); +assert.sameValue(instance.toString(), "-100000-07-01T21:30:36Z", "large negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-10000n)); +assert.sameValue(instance.toString(), "-010000-07-01T21:30:36Z", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-9999n)); +assert.sameValue(instance.toString(), "-009999-07-02T03:19:48Z", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1000n)); +assert.sameValue(instance.toString(), "-001000-07-02T09:30:36Z", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-999n)); +assert.sameValue(instance.toString(), "-000999-07-02T15:19:48Z", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(-1n)); +assert.sameValue(instance.toString(), "-000001-07-02T15:41:24Z", "year -1 formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(0n)); +assert.sameValue(instance.toString(), "0000-07-01T21:30:36Z", "year 0 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1n)); +assert.sameValue(instance.toString(), "0001-07-02T03:19:48Z", "year 1 formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(999n)); +assert.sameValue(instance.toString(), "0999-07-02T03:41:24Z", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(1000n)); +assert.sameValue(instance.toString(), "1000-07-02T09:30:36Z", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(9999n)); +assert.sameValue(instance.toString(), "9999-07-02T15:41:24Z", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.Instant(epochNsInYear(10000n)); +assert.sameValue(instance.toString(), "+010000-07-01T21:30:36Z", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.Instant(epochNsInYear(100000n)); +assert.sameValue(instance.toString(), "+100000-07-01T21:30:36Z", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js index 9d288cd6d6d..0837ea1dbb1 100644 --- a/test/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); const later = new Temporal.Instant(1_000_090_061_987_654_321n); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/Instant/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/Instant/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..c30976350c2 --- /dev/null +++ b/test/built-ins/Temporal/Instant/prototype/until/options-wrong-type.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.instant.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.Instant(0n); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.Instant(3600_000_000_000n), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js index 145ea2b808e..146b390014e 100644 --- a/test/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/Instant/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.Instant(1_000_000_000_000_000_000n); const later = new Temporal.Instant(1_000_090_061_987_654_321n); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js new file mode 100644 index 00000000000..8c0480b1d1a --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/compare/argument-string-invalid.js @@ -0,0 +1,66 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.compare +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a %%%conversion_target%%% +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const other = new Temporal.PlainDate(2020, 1, 1); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(arg, other), + `"${arg}" should not be a valid ISO string for a PlainDate (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainDate.compare(other, arg), + `"${arg}" should not be a valid ISO string for a PlainDate (second argument)` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/compare/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..e874d00f7cc --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/compare/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.plaindate.prototype.compare +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(); +Temporal.PlainDate.compare({ year: 2000, month: 5, day: 2, calendar }, { year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); diff --git a/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js index f0dee3ade9c..b59bdf35d49 100644 --- a/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js +++ b/test/built-ins/Temporal/PlainDate/from/argument-string-invalid.js @@ -1,30 +1,60 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// Copyright (C) 2022 Igalia S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-temporal.plaindate.from -description: overflow property is extracted with ISO-invalid string argument. -info: | - 1. Perform ? ToTemporalOverflow(_options_). - - 1. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. -includes: [compareArray.js, temporalHelpers.js] -features: [Temporal] +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] ---*/ -const expected = [ - "get overflow", - "get overflow.toString", - "call overflow.toString", +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", ]; - -let actual = []; -const object = { - get overflow() { - actual.push("get overflow"); - return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); - } -}; - -assert.throws(RangeError, () => Temporal.PlainDate.from("2020-13-34", object)); -assert.compareArray(actual, expected); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js new file mode 100644 index 00000000000..f0dee3ade9c --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string-invalid.js @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: overflow property is extracted with ISO-invalid string argument. +info: | + 1. Perform ? ToTemporalOverflow(_options_). + + 1. If ! IsValidISODate(year, month, day) is false, throw a RangeError exception. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get overflow", + "get overflow.toString", + "call overflow.toString", +]; + +let actual = []; +const object = { + get overflow() { + actual.push("get overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "overflow"); + } +}; + +assert.throws(RangeError, () => Temporal.PlainDate.from("2020-13-34", object)); +assert.compareArray(actual, expected); diff --git a/test/built-ins/Temporal/PlainDate/from/argument-string-overflow.js b/test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js similarity index 100% rename from test/built-ins/Temporal/PlainDate/from/argument-string-overflow.js rename to test/built-ins/Temporal/PlainDate/from/observable-get-overflow-argument-string.js diff --git a/test/built-ins/Temporal/PlainDate/from/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/from/options-wrong-type.js new file mode 100644 index 00000000000..73408176606 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.PlainDate.from({ year: 1976, month: 11, day: 18 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js index f04f77f745b..27e499961c5 100644 --- a/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/from/overflow-invalid-string.js @@ -34,8 +34,14 @@ const invalidOverflow = [ "CONSTRAIN", "constra\u0131n", ]; -validItems.forEach((item) => { - invalidOverflow.forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainDate.from(item, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const item of validItems) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDate.from(item, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/add/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/add/options-wrong-type.js new file mode 100644 index 00000000000..e33a0a90c01 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/add/options-wrong-type.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.plaindate.prototype.add +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.add({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js index 66282d2a6c3..6c7b65fd879 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/add/overflow-invalid-string.js @@ -18,6 +18,12 @@ features: [Temporal] const date = new Temporal.PlainDate(2000, 5, 2); const duration = new Temporal.Duration(3, 3, 0, 3); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => date.add(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js new file mode 100644 index 00000000000..ca71e4016a9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/equals/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.equals +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.equals(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..5de98aa4001 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/equals/calendar-datefromfields-called-with-options-undefined.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.plaindate.prototype.equals +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.equals({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js new file mode 100644 index 00000000000..45e74d668a5 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.since +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.since(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..782f4823b18 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-datefromfields-called-with-options-undefined.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.plaindate.prototype.since +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.since({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js index dbeb5699d69..86fdee9d580 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-default.js @@ -10,10 +10,10 @@ features: [Temporal] const feb20 = Temporal.PlainDate.from("2020-02-01"); const feb21 = Temporal.PlainDate.from("2021-02-01"); -TemporalHelpers.assertDuration(feb21.since(feb20), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no options"); -TemporalHelpers.assertDuration(feb21.since(feb20, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined options"); -TemporalHelpers.assertDuration(feb21.since(feb20, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit"); -TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); -TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "days"); -TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "auto"); -TemporalHelpers.assertDuration(feb21.since(feb20, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); +TemporalHelpers.assertDuration(feb21.since(feb20), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no options"); +TemporalHelpers.assertDuration(feb21.since(feb20, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined options"); +TemporalHelpers.assertDuration(feb21.since(feb20, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "auto"); +TemporalHelpers.assertDuration(feb21.since(feb20, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js index c1d8068ee4e..b3623a502e7 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-higher-units.js @@ -17,10 +17,10 @@ const feb20 = Temporal.PlainDate.from("2020-02-01"); const feb21 = Temporal.PlainDate.from("2021-02-01"); TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, years"); TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months"); -TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, 0, "start of February, weeks"); +TemporalHelpers.assertDuration(feb21.since(feb20, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, "start of February, weeks"); const lastFeb20 = Temporal.PlainDate.from("2020-02-29"); const lastFeb21 = Temporal.PlainDate.from("2021-02-28"); -TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "years" }), 0, /* months = */ 11, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, 0, "end of February, years"); +TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "years" }), 0, /* months = */ 11, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "end of February, years"); TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "months" }), 0, /* months = */ 11, 0, /* days = */ 28, 0, 0, 0, 0, 0, 0, "end of February, months"); TemporalHelpers.assertDuration(lastFeb21.since(lastFeb20, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js index 9b31fbaabcb..3b047aa86aa 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,30 @@ features: [Temporal] const earlier = new Temporal.PlainDate(2000, 5, 2); const later = new Temporal.PlainDate(2001, 6, 3); -const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..09905ce544b --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/since/options-wrong-type.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.plaindate.prototype.since +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.PlainDate(1976, 11, 18), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js index b06b57f530a..2bc9968ca67 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,30 @@ features: [Temporal] const earlier = new Temporal.PlainDate(2000, 5, 2); const later = new Temporal.PlainDate(2001, 6, 3); -const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/subtract/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/subtract/options-wrong-type.js new file mode 100644 index 00000000000..66584a29d6a --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/subtract/options-wrong-type.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.plaindate.prototype.subtract +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.subtract({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js index d3cbd6e8074..9387c6aff46 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/subtract/overflow-invalid-string.js @@ -18,6 +18,12 @@ features: [Temporal] const date = new Temporal.PlainDate(2000, 5, 2); const duration = new Temporal.Duration(3, 3, 0, 3); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => date.subtract(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js b/test/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..6f4864b4d62 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/toJSON/year-format.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.plaindate.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDate(-100000, 12, 3); +assert.sameValue(instance.toJSON(), "-100000-12-03", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-10000, 4, 5); +assert.sameValue(instance.toJSON(), "-010000-04-05", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-9999, 6, 7); +assert.sameValue(instance.toJSON(), "-009999-06-07", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1000, 8, 9); +assert.sameValue(instance.toJSON(), "-001000-08-09", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-999, 10, 9); +assert.sameValue(instance.toJSON(), "-000999-10-09", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1, 8, 7); +assert.sameValue(instance.toJSON(), "-000001-08-07", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDate(0, 6, 5); +assert.sameValue(instance.toJSON(), "0000-06-05", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDate(1, 4, 3); +assert.sameValue(instance.toJSON(), "0001-04-03", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDate(999, 2, 10); +assert.sameValue(instance.toJSON(), "0999-02-10", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(1000, 1, 23); +assert.sameValue(instance.toJSON(), "1000-01-23", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(9999, 4, 5); +assert.sameValue(instance.toJSON(), "9999-04-05", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(10000, 6, 7); +assert.sameValue(instance.toJSON(), "+010000-06-07", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDate(100000, 8, 9); +assert.sameValue(instance.toJSON(), "+100000-08-09", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..681c5f08a64 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.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.plaindate.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..6ef9df6b85f --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.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.plaindate.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDate/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..af7518abb73 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/toString/options-wrong-type.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.plaindate.prototype.tostring +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/toString/year-format.js b/test/built-ins/Temporal/PlainDate/prototype/toString/year-format.js new file mode 100644 index 00000000000..9c1d121aab2 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/toString/year-format.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.plaindate.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDate(-100000, 12, 3); +assert.sameValue(instance.toString(), "-100000-12-03", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-10000, 4, 5); +assert.sameValue(instance.toString(), "-010000-04-05", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-9999, 6, 7); +assert.sameValue(instance.toString(), "-009999-06-07", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1000, 8, 9); +assert.sameValue(instance.toString(), "-001000-08-09", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-999, 10, 9); +assert.sameValue(instance.toString(), "-000999-10-09", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDate(-1, 8, 7); +assert.sameValue(instance.toString(), "-000001-08-07", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDate(0, 6, 5); +assert.sameValue(instance.toString(), "0000-06-05", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDate(1, 4, 3); +assert.sameValue(instance.toString(), "0001-04-03", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDate(999, 2, 10); +assert.sameValue(instance.toString(), "0999-02-10", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(1000, 1, 23); +assert.sameValue(instance.toString(), "1000-01-23", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(9999, 4, 5); +assert.sameValue(instance.toString(), "9999-04-05", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDate(10000, 6, 7); +assert.sameValue(instance.toString(), "+010000-06-07", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDate(100000, 8, 9); +assert.sameValue(instance.toString(), "+100000-08-09", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js b/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js new file mode 100644 index 00000000000..4e59ac5e3f3 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.until +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.until(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..e55859f7278 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-datefromfields-called-with-options-undefined.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.plaindate.prototype.until +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDate(2000, 5, 2, calendar); +instance.until({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js index ea3f6679570..63b7fd397e6 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-default.js @@ -10,10 +10,10 @@ features: [Temporal] const feb20 = Temporal.PlainDate.from("2020-02-01"); const feb21 = Temporal.PlainDate.from("2021-02-01"); -TemporalHelpers.assertDuration(feb20.until(feb21), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no options"); -TemporalHelpers.assertDuration(feb20.until(feb21, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined options"); -TemporalHelpers.assertDuration(feb20.until(feb21, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit"); -TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); -TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "days"); -TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "auto"); -TemporalHelpers.assertDuration(feb20.until(feb21, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); +TemporalHelpers.assertDuration(feb20.until(feb21), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no options"); +TemporalHelpers.assertDuration(feb20.until(feb21, undefined), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined options"); +TemporalHelpers.assertDuration(feb20.until(feb21, {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: undefined }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "undefined largestUnit"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "days" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "days"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "auto" }), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "auto"); +TemporalHelpers.assertDuration(feb20.until(feb21, () => {}), 0, 0, 0, /* days = */ 366, 0, 0, 0, 0, 0, 0, "no largestUnit (function)"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js index 30c7ceec20c..30fd70ae2ae 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js @@ -17,7 +17,7 @@ const feb20 = Temporal.PlainDate.from("2020-02-01"); const feb21 = Temporal.PlainDate.from("2021-02-01"); TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, years"); TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months"); -TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, 0, "start of February, weeks"); +TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, "start of February, weeks"); const lastFeb20 = Temporal.PlainDate.from("2020-02-29"); const lastFeb21 = Temporal.PlainDate.from("2021-02-28"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js index b06f5d6ed85..379dd28424d 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,30 @@ features: [Temporal] const earlier = new Temporal.PlainDate(2000, 5, 2); const later = new Temporal.PlainDate(2001, 6, 3); -const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..e93369500ed --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/until/options-wrong-type.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.plaindate.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.PlainDate(1976, 11, 18), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js index 3eb01aaee89..8382c5c924c 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,30 @@ features: [Temporal] const earlier = new Temporal.PlainDate(2000, 5, 2); const later = new Temporal.PlainDate(2001, 6, 3); -const values = ["era", "eraYear", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainDate/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/PlainDate/prototype/with/options-wrong-type.js new file mode 100644 index 00000000000..0fdb1c24e6d --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/with/options-wrong-type.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.plaindate.prototype.with +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDate(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ day: 5 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js index d35f66be86b..acef874825b 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDate/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const date = new Temporal.PlainDate(2000, 5, 2); -["", "CONSTRAIN", "balance", "other string"].forEach((overflow) => - assert.throws(RangeError, () => date.with({ month: 8 }, { overflow })) -); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/compare/basic.js b/test/built-ins/Temporal/PlainDateTime/compare/basic.js index a47e91cd628..17cd7104252 100644 --- a/test/built-ins/Temporal/PlainDateTime/compare/basic.js +++ b/test/built-ins/Temporal/PlainDateTime/compare/basic.js @@ -9,21 +9,14 @@ features: [Temporal] const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const dt3 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const dt4 = new Temporal.PlainDateTime(2019, 10, 29, 15, 23, 30, 123, 456, 789); +const dt5 = new Temporal.PlainDateTime(1976, 11, 18, 10, 46, 38, 271, 986, 102); -assert.sameValue( - Temporal.PlainDateTime.compare(dt1, dt1), - 0, - "equal" -); +assert.sameValue(Temporal.PlainDateTime.compare(dt1, dt1), 0, "equal"); +assert.sameValue(Temporal.PlainDateTime.compare(dt1, dt2), -1, "smaller/larger"); +assert.sameValue(Temporal.PlainDateTime.compare(dt2, dt1), 1, "larger/smaller"); +assert.sameValue(Temporal.PlainDateTime.compare(dt2, dt3), 0, "equal different object"); +assert.sameValue(Temporal.PlainDateTime.compare(dt3, dt4), -1, "same date, earlier time"); +assert.sameValue(Temporal.PlainDateTime.compare(dt3, dt5), 1, "same time, later date"); -assert.sameValue( - Temporal.PlainDateTime.compare(dt1, dt2), - -1, - "smaller/larger" -); - -assert.sameValue( - Temporal.PlainDateTime.compare(dt2, dt1), - 1, - "larger/smaller" -); diff --git a/test/built-ins/Temporal/PlainDateTime/compare/calendar-ignored.js b/test/built-ins/Temporal/PlainDateTime/compare/calendar-ignored.js new file mode 100644 index 00000000000..9f197ae0a62 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/compare/calendar-ignored.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.plaindatetime.compare +description: Calendar is not taken into account for the comparison. +features: [Temporal] +---*/ + +const calendar1 = { toString() { throw new Test262Error("should not call calendar1.toString") } }; +const calendar2 = { toString() { throw new Test262Error("should not call calendar2.toString") } }; +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar1); +const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102, calendar1); +const dt3 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102, calendar1); +const dt4 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102, calendar2); + +assert.sameValue(Temporal.PlainDateTime.compare(dt1, dt2), -1, "smaller"); +assert.sameValue(Temporal.PlainDateTime.compare(dt2, dt3), 0, "equal with same calendar"); +assert.sameValue(Temporal.PlainDateTime.compare(dt2, dt4), 0, "equal with different calendar"); diff --git a/test/built-ins/Temporal/PlainDateTime/from/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/from/options-wrong-type.js new file mode 100644 index 00000000000..df34d81b64c --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.PlainDateTime.from({ year: 1976, month: 11, day: 18 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js index 41673499f72..1786ed59049 100644 --- a/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/from/overflow-invalid-string.js @@ -31,6 +31,14 @@ const validValues = [ { year: 2000, month: 5, day: 2, hour: 12 }, "2000-05-02T12:00", ]; -validValues.forEach((value) => { - assert.throws(RangeError, () => Temporal.PlainDateTime.from(value, { overflow: "other string" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-wrong-type.js new file mode 100644 index 00000000000..68c33eb4970 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.add +description: 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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.add({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js index 40124a8f32d..6ce6ecc29de 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/add/overflow-invalid-string.js @@ -21,11 +21,12 @@ features: [Temporal] const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); const duration = new Temporal.Duration(3, 3, 0, 3, 3); -const badOverflows = ['', 'CONSTRAIN', 'balance', "other string"]; -badOverflows.forEach((overflow) => { + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { assert.throws( RangeError, () => datetime.add({ months: 1 }, { overflow }), `invalid overflow ("${overflow}")` ); -}); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js index c83cffeef4e..72133b1e514 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/basic.js @@ -9,6 +9,12 @@ features: [Temporal] const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); const dt2 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const dt3 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102); +const dt4 = new Temporal.PlainDateTime(2019, 10, 29, 15, 23, 30, 123, 456, 789); +const dt5 = new Temporal.PlainDateTime(1976, 11, 18, 10, 46, 38, 271, 986, 102); assert.sameValue(dt1.equals(dt1), true, "equal"); assert.sameValue(dt1.equals(dt2), false, "unequal"); +assert.sameValue(dt2.equals(dt3), true, "equal with different objects"); +assert.sameValue(dt2.equals(dt4), false, "same date, different time"); +assert.sameValue(dt2.equals(dt5), false, "same time, different date"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-checked.js b/test/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-checked.js new file mode 100644 index 00000000000..de8dfabf30e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/equals/calendar-checked.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.equals +description: Calendar is taken into account if the ISO data is equal +includes: [compareArray.js,temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const calendar1 = TemporalHelpers.toPrimitiveObserver(actual, "A", "calendar1"); +const calendar2 = TemporalHelpers.toPrimitiveObserver(actual, "A", "calendar2"); +const calendar3 = TemporalHelpers.toPrimitiveObserver(actual, "B", "calendar3"); +const dt1 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar1); +const dt1b = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar1); +const dt2 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar2); +const dt3 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar3); + +assert.sameValue(dt1.equals(dt1b), true, "same calendar object"); +assert.compareArray(actual, []); + +assert.sameValue(dt1.equals(dt2), true, "same calendar string"); +assert.compareArray(actual, ["get calendar1.toString", "call calendar1.toString", "get calendar2.toString", "call calendar2.toString"]); + +actual.splice(0, actual.length); // empty it for the next check +assert.sameValue(dt1.equals(dt3), false, "different calendar string"); +assert.compareArray(actual, ["get calendar1.toString", "call calendar1.toString", "get calendar3.toString", "call calendar3.toString"]); + +const calendar4 = { toString() { throw new Test262Error("should not call calendar4.toString") } }; +const calendar5 = { toString() { throw new Test262Error("should not call calendar5.toString") } }; +const dt4 = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789, calendar4); +const dt5 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102, calendar4); +const dt6 = new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38, 271, 986, 102, calendar5); +assert.sameValue(dt4.equals(dt5), false, "not equal same calendar"); +assert.sameValue(dt4.equals(dt6), false, "not equal different calendar"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/balance.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/balance.js new file mode 100644 index 00000000000..37a7947b6e3 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/balance.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.plaindatetime.prototype.round +description: Rounding balances to the next smallest unit +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 23, 59, 59, 999, 999, 999); + +["day", "hour", "minute", "second", "millisecond", "microsecond"].forEach((smallestUnit) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit }), + 1976, 11, "M11", 19, 0, 0, 0, 0, 0, 0, + `balances to next ${smallestUnit}` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/options-wrong-type.js new file mode 100644 index 00000000000..eaf7bd764a6 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/options-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-temporal.plaindatetime.prototype.round +description: TypeError thrown when options argument is missing or a non-string primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainDateTime(2000, 5, 2); +assert.throws(TypeError, () => instance.round(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.round(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/rounding-direction.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/rounding-direction.js new file mode 100644 index 00000000000..5e0e1eaeca4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/rounding-direction.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.plaindatetime.prototype.round +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(-99, 12, 15, 12, 0, 0, 500); +TemporalHelpers.assertPlainDateTime( + instance.round({ smallestUnit: "second", roundingMode: "floor" }), + -99, 12, "M12", 15, 12, 0, 0, 0, 0, 0, + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode floor)" +); +TemporalHelpers.assertPlainDateTime( + instance.round({ smallestUnit: "second", roundingMode: "trunc" }), + -99, 12, "M12", 15, 12, 0, 0, 0, 0, 0, + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +TemporalHelpers.assertPlainDateTime( + instance.round({ smallestUnit: "second", roundingMode: "ceil" }), + -99, 12, "M12", 15, 12, 0, 1, 0, 0, 0, + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +TemporalHelpers.assertPlainDateTime( + instance.round({ smallestUnit: "second", roundingMode: "halfExpand" }), + -99, 12, "M12", 15, 12, 0, 1, 0, 0, 0, + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-divides.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-divides.js new file mode 100644 index 00000000000..304046e331d --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-divides.js @@ -0,0 +1,53 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Rounding increment should properly divide the relevant time unit +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +[1, 2, 3, 4, 6, 8, 12].forEach((roundingIncrement) => { + assert.sameValue( + dt.round({ smallestUnit: "hour", roundingIncrement }) instanceof Temporal.PlainDateTime, + true, + `valid hour increments divide into 24 (rounding increment = ${roundingIncrement})`); +}); + +["minute", "second"].forEach((smallestUnit) => { + [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30].forEach((roundingIncrement) => { + assert.sameValue( + dt.round({ smallestUnit, roundingIncrement }) instanceof Temporal.PlainDateTime, + true, + `valid ${smallestUnit} increments divide into 60 (rounding increment = ${roundingIncrement})` + ); + }); +}); + +["millisecond", "microsecond", "nanosecond"].forEach((smallestUnit) => { + [1, 2, 4, 5, 8, 10, 20, 25, 40, 50, 100, 125, 200, 250, 500].forEach((roundingIncrement) => { + assert.sameValue( + dt.round({ smallestUnit, roundingIncrement }) instanceof Temporal.PlainDateTime, + true, + `valid ${smallestUnit} increments divide into 1000 (rounding increment = ${roundingIncrement})`); + }); +}); + +const nextIncrements = { + "hour": 24, + "minute": 60, + "second": 60, + "millisecond": 1000, + "microsecond": 1000, + "nanosecond": 1000 +}; + +Object.entries(nextIncrements).forEach(([unit, next]) => { + assert.throws( + RangeError, + () => dt.round({ smallestUnit: unit, roundingIncrement: next }), + `throws on increments that are equal to the next highest (unit = ${unit}, increment = ${next})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-does-not-divide.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-does-not-divide.js new file mode 100644 index 00000000000..82ab14b519c --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-does-not-divide.js @@ -0,0 +1,18 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Throw exception if the rounding unit does not properly divide the relevant time unit +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); +const units = ["day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; +units.forEach((unit) => { + assert.throws( + RangeError, + () => dt.round({ smallestUnit: unit, roundingIncrement: 29 }), + `throws on increments that do not divide evenly into the next highest (unit = ${unit})` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-one-day.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-one-day.js new file mode 100644 index 00000000000..71470b4bb9c --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingincrement-one-day.js @@ -0,0 +1,17 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: One day is a valid rounding increment +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "day", roundingIncrement: 1 }), + 1976, 11, "M11", 19, 0, 0, 0, 0, 0, 0, + "1 day is a valid increment" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-basic.js new file mode 100644 index 00000000000..d434095df9a --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-basic.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Basic checks for rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "hour", roundingIncrement: 4 }), + 1976, 11, "M11", 18, 16, 0, 0, 0, 0, 0, + "rounds to an increment of hours" +); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "minute", roundingIncrement: 15 }), + 1976, 11, "M11", 18, 14, 30, 0, 0, 0, 0, + "rounds to an increment of minutes" +); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "second", roundingIncrement: 30 }), + 1976, 11, "M11", 18, 14, 23, 30, 0, 0, 0, + "rounds to an increment of seconds" +); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "millisecond", roundingIncrement: 10 }), + 1976, 11, "M11", 18, 14, 23, 30, 120, 0, 0, + "rounds to an increment of milliseconds" +); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "microsecond", roundingIncrement: 10 }), + 1976, 11, "M11", 18, 14, 23, 30, 123, 460, 0, + "rounds to an increment of microseconds" +); + +TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: "nanosecond", roundingIncrement: 10 }), + 1976, 11, "M11", 18, 14, 23, 30, 123, 456, 790, + "rounds to an increment of nanoseconds" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-ceil-basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-ceil-basic.js new file mode 100644 index 00000000000..3e290c93178 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-ceil-basic.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Basic checks for ceiling rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +const incrementOneCeil = { + "day": [1976, 11, "M11", 19, 0, 0, 0, 0, 0, 0], + "hour": [1976, 11, "M11", 18, 15, 0, 0, 0, 0, 0], + "minute": [1976, 11, "M11", 18, 14, 24, 0, 0, 0, 0], + "second": [1976, 11, "M11", 18, 14, 23, 31, 0, 0, 0], + "millisecond": [1976, 11, "M11", 18, 14, 23, 30, 124, 0, 0], + "microsecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 457, 0], + "nanosecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 789] +}; + +Object.entries(incrementOneCeil).forEach(([smallestUnit, expected]) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit, roundingMode: "ceil" }), + ...expected, + `rounds up to ${smallestUnit} (ceil)`, + undefined + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-floor-basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-floor-basic.js new file mode 100644 index 00000000000..8379b6100f8 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-floor-basic.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Basic checks for the floor rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +const incrementOneFloor = { + "day": [1976, 11, "M11", 18, 0, 0, 0, 0, 0, 0], + "hour": [1976, 11, "M11", 18, 14, 0, 0, 0, 0, 0], + "minute": [1976, 11, "M11", 18, 14, 23, 0, 0, 0, 0], + "second": [1976, 11, "M11", 18, 14, 23, 30, 0, 0, 0], + "millisecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 0, 0], + "microsecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 0], + "nanosecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 789] +}; + +Object.entries(incrementOneFloor).forEach(([smallestUnit, expected]) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit, roundingMode: "floor" }), + ...expected, + `rounds down to ${smallestUnit} (floor)` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-basic.js new file mode 100644 index 00000000000..5cb4275c3aa --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-basic.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Basic checks for half-expand rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +const incrementOneNearest = { + "day": [1976, 11, "M11", 19, 0, 0, 0, 0, 0, 0], + "hour": [1976, 11, "M11", 18, 14, 0, 0, 0, 0, 0], + "minute": [1976, 11, "M11", 18, 14, 24, 0, 0, 0, 0], + "second": [1976, 11, "M11", 18, 14, 23, 30, 0, 0, 0], + "millisecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 0, 0], + "microsecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 457, 0], + "nanosecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 789] +}; + +Object.entries(incrementOneNearest).forEach(([smallestUnit, expected]) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit, roundingMode: "halfExpand" }), + ...expected, + `rounds to nearest ${smallestUnit} (half-expand)`, + undefined + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-is-default.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-is-default.js new file mode 100644 index 00000000000..47274d17459 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-halfexpand-is-default.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.plaindatetime.prototype.round +description: Half-expand is the default rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +const units = { + "day": [1976, 11, "M11", 19, 0, 0, 0, 0, 0, 0], + "hour": [1976, 11, "M11", 18, 14, 0, 0, 0, 0, 0], + "minute": [1976, 11, "M11", 18, 14, 24, 0, 0, 0, 0], + "second": [1976, 11, "M11", 18, 14, 23, 30, 0, 0, 0], + "millisecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 0, 0], + "microsecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 457, 0], + "nanosecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 789] +}; + +const expected = [1976, 11, "M11", 18, 0, 0, 0, 0, 0, 0]; + +Object.entries(units).forEach(([unit, expected]) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit: unit }), + ...expected, + `halfExpand is the default (smallest unit = ${unit}, rounding mode absent)` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-trunc-basic.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-trunc-basic.js new file mode 100644 index 00000000000..c8f0a278488 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/roundingmode-trunc-basic.js @@ -0,0 +1,29 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Basic checks for truncation rounding mode +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +const incrementOneFloor = { + "day": [1976, 11, "M11", 18, 0, 0, 0, 0, 0, 0], + "hour": [1976, 11, "M11", 18, 14, 0, 0, 0, 0, 0], + "minute": [1976, 11, "M11", 18, 14, 23, 0, 0, 0, 0], + "second": [1976, 11, "M11", 18, 14, 23, 30, 0, 0, 0], + "millisecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 0, 0], + "microsecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 0], + "nanosecond": [1976, 11, "M11", 18, 14, 23, 30, 123, 456, 789] +}; + +Object.entries(incrementOneFloor).forEach(([smallestUnit, expected]) => { + TemporalHelpers.assertPlainDateTime( + dt.round({ smallestUnit, roundingMode: "trunc" }), + ...expected, + `truncates to ${smallestUnit}` + ); +}); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js index e4d8f8503c1..f37ebe513cc 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/smallestunit-invalid-string.js @@ -8,4 +8,26 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => datetime.round({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object-insufficient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object-insufficient-data.js new file mode 100644 index 00000000000..7f57d1d220a --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object-insufficient-data.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Throw if smallest unit is missing from argument +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +assert.throws( + RangeError, + () => dt.round({ roundingIncrement: 1, roundingMode: "ceil" }), + "throws without required smallestUnit parameter" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object.js new file mode 100644 index 00000000000..8ca7977a4e9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Throw if argument is an empty plain object +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +assert.throws( + RangeError, + () => dt.round({}), + "throws on empty object" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-no-argument.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-no-argument.js new file mode 100644 index 00000000000..d75fe284628 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-no-argument.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Throw if no arguments at all are given +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => dt.round(), + "throws without any parameters" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-undefined.js b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-undefined.js new file mode 100644 index 00000000000..7b49ded8ddc --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/round/throws-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.round +description: Throw if sole argument is undefined +features: [Temporal] +---*/ + +const dt = new Temporal.PlainDateTime(1976, 11, 18, 14, 23, 30, 123, 456, 789); + +assert.throws( + TypeError, + () => dt.round(undefined), + "throws without undefined as sole parameter" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js index 1e8f9c80548..547667d70d3 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..ef026cc97c3 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.since +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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.PlainDateTime(1976, 11, 18), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js index a031b3f0fff..6fc80aa6a06 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-wrong-type.js new file mode 100644 index 00000000000..38172d541d8 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.subtract +description: 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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.subtract({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js index 1e1f1761c81..c3e4b694f44 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/subtract/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] const date = new Temporal.PlainDateTime(2000, 5, 2, 12); const duration = new Temporal.Duration(3, 3, 0, 3, 3); -assert.throws(RangeError, () => date.subtract(duration, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => date.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js b/test/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..261e9e6ec07 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toJSON/year-format.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDateTime(-100000, 12, 3, 4, 56, 7, 890); +assert.sameValue(instance.toJSON(), "-100000-12-03T04:56:07.89", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-10000, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toJSON(), "-010000-04-05T06:07:08.91", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-9999, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toJSON(), "-009999-06-07T08:09:10.987", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toJSON(), "-001000-08-09T10:09:08.765", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-999, 10, 9, 8, 7, 6, 543); +assert.sameValue(instance.toJSON(), "-000999-10-09T08:07:06.543", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1, 8, 7, 6, 54, 32, 100); +assert.sameValue(instance.toJSON(), "-000001-08-07T06:54:32.1", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(0, 6, 5, 4, 32, 10, 123); +assert.sameValue(instance.toJSON(), "0000-06-05T04:32:10.123", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1, 4, 3, 21, 0, 12, 345); +assert.sameValue(instance.toJSON(), "0001-04-03T21:00:12.345", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(999, 2, 10, 12, 34, 56, 789); +assert.sameValue(instance.toJSON(), "0999-02-10T12:34:56.789", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1000, 1, 23, 4, 56, 7, 890); +assert.sameValue(instance.toJSON(), "1000-01-23T04:56:07.89", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(9999, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toJSON(), "9999-04-05T06:07:08.91", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(10000, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toJSON(), "+010000-06-07T08:09:10.987", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(100000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toJSON(), "+100000-08-09T10:09:08.765", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..ee8746eb4b0 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..0a8deb44c9e --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-auto.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 00000000000..2567d042758 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-auto.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [Temporal] +---*/ + +const zeroSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23); +const wholeSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30); +const subSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 400); + +const tests = [ + [zeroSeconds, "1976-11-18T15:23:00"], + [wholeSeconds, "1976-11-18T15:23:30"], + [subSeconds, "1976-11-18T15:23:30.1234"], +]; + +for (const [datetime, expected] of tests) { + assert.sameValue(datetime.toString(), expected, "default is to emit seconds and drop trailing zeroes"); + assert.sameValue(datetime.toString({ fractionalSecondDigits: "auto" }), expected, "auto is the default"); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js index 150d868658a..9fa496c2955 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -10,10 +10,13 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaindatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos", "auto\0"]) { + assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js index 7de58c30b34..281d78f1abd 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -10,7 +10,7 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaindatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-number.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 00000000000..843ef74f788 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-number.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.plaindatetime.prototype.tostring +description: Number for fractionalSecondDigits option +features: [Temporal] +---*/ + +const zeroSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23); +const wholeSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30); +const subSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 400); + +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 0 }), "1976-11-18T15:23:30", + "truncates 4 decimal places to 0"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 2 }), "1976-11-18T15:23:00.00", + "pads zero seconds to 2 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 2 }), "1976-11-18T15:23:30.00", + "pads whole seconds to 2 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 2 }), "1976-11-18T15:23:30.12", + "truncates 4 decimal places to 2"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 3 }), "1976-11-18T15:23:30.123", + "truncates 4 decimal places to 3"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 6 }), "1976-11-18T15:23:30.123400", + "pads 4 decimal places to 6"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 7 }), "1976-11-18T15:23:00.0000000", + "pads zero seconds to 7 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 7 }), "1976-11-18T15:23:30.0000000", + "pads whole seconds to 7 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 7 }), "1976-11-18T15:23:30.1234000", + "pads 4 decimal places to 7"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 9 }), "1976-11-18T15:23:30.123400000", + "pads 4 decimal places to 9"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js index 948d707eb35..2ccbafaeec0 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -10,11 +10,17 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaindatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 })); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -Infinity }), + "−∞ is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 }), + "−1 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 }), + "10 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: Infinity }), + "∞ is out of range for fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js index 12a0f77b873..d5ebb9c7e68 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-undefined.js @@ -8,17 +8,31 @@ info: | sec-getoption step 3: 3. If _value_ is *undefined*, return _fallback_. sec-getstringornumberoption step 2: - 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaindatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ -const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); +const zeroSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23); +const wholeSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30); +const subSeconds = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 400); -const explicit = datetime.toString({ fractionalSecondDigits: undefined }); -assert.sameValue(explicit, "2000-05-02T12:34:56.98765", "default fractionalSecondDigits is auto"); +const tests = [ + [zeroSeconds, "1976-11-18T15:23:00"], + [wholeSeconds, "1976-11-18T15:23:30"], + [subSeconds, "1976-11-18T15:23:30.1234"], +]; -// See options-undefined.js for {} +for (const [datetime, expected] of tests) { + const explicit = datetime.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); + + const implicit = datetime.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); + + const lambda = datetime.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js index 9177b82196a..5ecaf7a6d1f 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -22,4 +22,26 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 650, 0); -TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: null }), + "null is not a number and converts to the string 'null' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: true }), + "true is not a number and converts to the string 'true' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: false }), + "false is not a number and converts to the string 'false' which is not valid for fractionalSecondDigits"); +assert.throws(TypeError, () => datetime.toString({ fractionalSecondDigits: Symbol() }), + "symbols are not numbers and cannot convert to strings"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 2n }), + "bigints are not numbers and convert to strings which are not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: {} }), + "plain objects are not numbers and convert to strings which are not valid for fractionalSecondDigits"); + +const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); +const result = datetime.toString({ fractionalSecondDigits: observer }); +assert.sameValue(result, "2000-05-02T12:34:56.98765", "object with toString uses toString return value"); +assert.compareArray(actual, expected, "object with toString calls toString and not valueOf"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..b535b7e07c9 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-cross-midnight.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-cross-midnight.js new file mode 100644 index 00000000000..fe29b3b9c51 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-cross-midnight.js @@ -0,0 +1,13 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Rounding can cross midnight +features: [Temporal] +---*/ + +const plainDateTime = new Temporal.PlainDateTime(1999, 12, 31, 23, 59, 59, 999, 999, 999); // one nanosecond before 2000-01-01T00:00:00 +for (const roundingMode of ["ceil", "halfExpand"]) { + assert.sameValue(plainDateTime.toString({ fractionalSecondDigits: 8, roundingMode }), "2000-01-01T00:00:00.00000000"); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-direction.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-direction.js new file mode 100644 index 00000000000..a4d7dec32d7 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/rounding-direction.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(-99, 12, 15, 12, 0, 0, 500); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "floor" }), + "-000099-12-15T12:00:00", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "trunc" }), + "-000099-12-15T12:00:00", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "ceil" }), + "-000099-12-15T12:00:01", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "halfExpand" }), + "-000099-12-15T12:00:01", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-ceil.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-ceil.js new file mode 100644 index 00000000000..762b3a5cd33 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-ceil.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.plaindatetime.prototype.tostring +description: ceil value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); +assert.sameValue(result1, "2000-05-02T12:34:56.123988", + "roundingMode is ceil (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "ceil" }); +assert.sameValue(result2, "2000-05-02T12:34:56.123988", + "roundingMode is ceil (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result3, "2000-05-02T12:34:56.124", + "roundingMode is ceil (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "ceil" }); +assert.sameValue(result4, "2000-05-02T12:34:56.124", + "roundingMode is ceil (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result5, "2000-05-02T12:34:57", + "roundingMode is ceil (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "ceil" }); +assert.sameValue(result6, "2000-05-02T12:34:57", + "roundingMode is ceil (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "ceil" }); +assert.sameValue(result7, "2000-05-02T12:35", "roundingMode is ceil (round to minute)"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-floor.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-floor.js new file mode 100644 index 00000000000..4899d4cfa26 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-floor.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.plaindatetime.prototype.tostring +description: floor value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); +assert.sameValue(result1, "2000-05-02T12:34:56.123987", + "roundingMode is floor (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "floor" }); +assert.sameValue(result2, "2000-05-02T12:34:56.123987", + "roundingMode is floor (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result3, "2000-05-02T12:34:56.123", + "roundingMode is floor (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "floor" }); +assert.sameValue(result4, "2000-05-02T12:34:56.123", + "roundingMode is floor (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result5, "2000-05-02T12:34:56", + "roundingMode is floor (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "floor" }); +assert.sameValue(result6, "2000-05-02T12:34:56", + "roundingMode is floor (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "floor" }); +assert.sameValue(result7, "2000-05-02T12:34", "roundingMode is floor (round to minute)"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-halfExpand.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 00000000000..9dcad461121 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-halfExpand.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.plaindatetime.prototype.tostring +description: halfExpand value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); +assert.sameValue(result1, "2000-05-02T12:34:56.123988", + "roundingMode is halfExpand (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "halfExpand" }); +assert.sameValue(result2, "2000-05-02T12:34:56.123988", + "roundingMode is halfExpand (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result3, "2000-05-02T12:34:56.124", + "roundingMode is halfExpand (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "halfExpand" }); +assert.sameValue(result4, "2000-05-02T12:34:56.124", + "roundingMode is halfExpand (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result5, "2000-05-02T12:34:56", + "roundingMode is halfExpand (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "halfExpand" }); +assert.sameValue(result6, "2000-05-02T12:34:56", + "roundingMode is halfExpand (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "halfExpand" }); +assert.sameValue(result7, "2000-05-02T12:35", "roundingMode is halfExpand (round to minute)"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-trunc.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-trunc.js new file mode 100644 index 00000000000..fa3e86319fc --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/roundingmode-trunc.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.plaindatetime.prototype.tostring +description: trunc value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); +assert.sameValue(result1, "2000-05-02T12:34:56.123987", + "roundingMode is trunc (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "trunc" }); +assert.sameValue(result2, "2000-05-02T12:34:56.123987", + "roundingMode is trunc (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result3, "2000-05-02T12:34:56.123", + "roundingMode is trunc (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "trunc" }); +assert.sameValue(result4, "2000-05-02T12:34:56.123", + "roundingMode is trunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result5, "2000-05-02T12:34:56", + "roundingMode is trunc (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "trunc" }); +assert.sameValue(result6, "2000-05-02T12:34:56", + "roundingMode is trunc (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "trunc" }); +assert.sameValue(result7, "2000-05-02T12:34", "roundingMode is trunc (round to minute)"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-fractionalseconddigits.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 00000000000..9918d045fc7 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-fractionalseconddigits.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 12, 34, 56, 789, 999, 999); +const tests = [ + ["minute", "1976-11-18T12:34"], + ["second", "1976-11-18T12:34:56"], + ["millisecond", "1976-11-18T12:34:56.789"], + ["microsecond", "1976-11-18T12:34:56.789999"], + ["nanosecond", "1976-11-18T12:34:56.789999999"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = datetime.toString({ + smallestUnit, + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } + }); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); +} + +assert.throws(RangeError, () => datetime.toString({ + smallestUnit: "hour", + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js index 1d1a6aaeca2..10e19530c1a 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-invalid-string.js @@ -8,4 +8,30 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 987, 500); -assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "hour", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "hours", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js index 34928a9c6d9..6aff7a613b2 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/smallestunit-valid-units.js @@ -7,15 +7,41 @@ description: Valid units for the smallestUnit option features: [Temporal] ---*/ -const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 789, 999, 999); +const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 123, 456, 789); -assert.sameValue(datetime.toString({ smallestUnit: "minute" }), "2000-05-02T12:34"); -assert.sameValue(datetime.toString({ smallestUnit: "second" }), "2000-05-02T12:34:56"); -assert.sameValue(datetime.toString({ smallestUnit: "millisecond" }), "2000-05-02T12:34:56.789"); -assert.sameValue(datetime.toString({ smallestUnit: "microsecond" }), "2000-05-02T12:34:56.789999"); -assert.sameValue(datetime.toString({ smallestUnit: "nanosecond" }), "2000-05-02T12:34:56.789999999"); +function test(instance, expectations, description) { + for (const [smallestUnit, expectedResult] of expectations) { + assert.sameValue(instance.toString({ smallestUnit }), expectedResult, + `${description} with smallestUnit "${smallestUnit}"`); + } +} + +test( + datetime, + [ + ["minute", "2000-05-02T12:34"], + ["second", "2000-05-02T12:34:56"], + ["millisecond", "2000-05-02T12:34:56.123"], + ["microsecond", "2000-05-02T12:34:56.123456"], + ["nanosecond", "2000-05-02T12:34:56.123456789"], + ], + "subseconds toString" +); + +test( + new Temporal.PlainDateTime(2000, 5, 2, 12, 34), + [ + ["minute", "2000-05-02T12:34"], + ["second", "2000-05-02T12:34:00"], + ["millisecond", "2000-05-02T12:34:00.000"], + ["microsecond", "2000-05-02T12:34:00.000000"], + ["nanosecond", "2000-05-02T12:34:00.000000000"], + ], + "whole minutes toString" +); const notValid = [ + "era", "year", "month", "week", @@ -24,5 +50,6 @@ const notValid = [ ]; notValid.forEach((smallestUnit) => { - assert.throws(RangeError, () => datetime.toString({ smallestUnit }), smallestUnit); + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); }); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js b/test/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js new file mode 100644 index 00000000000..d94ed41240f --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toString/year-format.js @@ -0,0 +1,47 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainDateTime(-100000, 12, 3, 4, 56, 7, 890); +assert.sameValue(instance.toString(), "-100000-12-03T04:56:07.89", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-10000, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toString(), "-010000-04-05T06:07:08.91", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-9999, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toString(), "-009999-06-07T08:09:10.987", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toString(), "-001000-08-09T10:09:08.765", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-999, 10, 9, 8, 7, 6, 543); +assert.sameValue(instance.toString(), "-000999-10-09T08:07:06.543", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(-1, 8, 7, 6, 54, 32, 100); +assert.sameValue(instance.toString(), "-000001-08-07T06:54:32.1", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(0, 6, 5, 4, 32, 10, 123); +assert.sameValue(instance.toString(), "0000-06-05T04:32:10.123", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1, 4, 3, 21, 0, 12, 345); +assert.sameValue(instance.toString(), "0001-04-03T21:00:12.345", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(999, 2, 10, 12, 34, 56, 789); +assert.sameValue(instance.toString(), "0999-02-10T12:34:56.789", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(1000, 1, 23, 4, 56, 7, 890); +assert.sameValue(instance.toString(), "1000-01-23T04:56:07.89", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(9999, 4, 5, 6, 7, 8, 910); +assert.sameValue(instance.toString(), "9999-04-05T06:07:08.91", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainDateTime(10000, 6, 7, 8, 9, 10, 987); +assert.sameValue(instance.toString(), "+010000-06-07T08:09:10.987", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainDateTime(100000, 8, 9, 10, 9, 8, 765); +assert.sameValue(instance.toString(), "+100000-08-09T10:09:08.765", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-wrong-type.js new file mode 100644 index 00000000000..c2a63768399 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toZonedDateTime("UTC", value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js index a3cf0f6aff3..aa7ca9a4c34 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); const later = new Temporal.PlainDateTime(2001, 6, 3, 13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..6b248d2e110 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: 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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.PlainDateTime(1976, 11, 18), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js index 781434f7af6..d12bb40e32c 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 0, 0, 0); const later = new Temporal.PlainDateTime(2000, 5, 3, 13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js new file mode 100644 index 00000000000..e13f520ea33 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/units-changed.js @@ -0,0 +1,66 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.until +description: Largest unit is respected +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const feb20 = new Temporal.PlainDateTime(2020, 2, 1, 0, 0); +const feb21 = new Temporal.PlainDateTime(2021, 2, 1, 0, 0); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "years" }), + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (years)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "months" }), + 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (months)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "weeks" }), + 0, 0, 52, 2, 0, 0, 0, 0, 0, 0, + "can return lower or higher units (weeks)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "hours" }), + 0, 0, 0, 0, 8784, 0, 0, 0, 0, 0, + "can return lower or higher units (hours)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "minutes" }), + 0, 0, 0, 0, 0, 527040, 0, 0, 0, 0, + "can return lower or higher units (minutes)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "seconds" }), + 0, 0, 0, 0, 0, 0, 31622400, 0, 0, 0, + "can return lower or higher units (seconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, 31622400000, 0, 0, + "can return lower or higher units (milliseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000, 0, + "can return lower or higher units (microseconds)" +); + +TemporalHelpers.assertDuration( + feb20.until(feb21, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 31622400000000000, + "can return lower or higher units (nanoseconds)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-not-object.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-not-object.js new file mode 100644 index 00000000000..65c474da538 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/argument-not-object.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: Non-object arguments throw. +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +const args = [ + undefined, + null, + true, + "2020-01-12T10:20:30", + Symbol(), + 2020, + 2020n, +]; +for (const argument of args) { + assert.throws(TypeError, () => instance.with(argument), `Does not support ${typeof argument}`); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-options.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-options.js new file mode 100644 index 00000000000..935c1333d12 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-options.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.plaindatetime.prototype.with +description: The options argument is passed through to Calendar#dateFromFields as-is. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const options = {}; +let calledDateFromFields = 0; +class Calendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + } + dateFromFields(fields, optionsArg) { + ++calledDateFromFields; + assert.sameValue(optionsArg, options, "should pass options object through"); + return super.dateFromFields(fields, optionsArg); + } +}; +const calendar = new Calendar(); +const plaindatetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +const result = plaindatetime.with({ year: 2005 }, options); +TemporalHelpers.assertPlainDateTime(result, 2005, 5, "M05", 2, 12, 34, 56, 987, 654, 321); +assert.sameValue(calledDateFromFields, 1, "should have called overridden dateFromFields once"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws.js new file mode 100644 index 00000000000..ae6887e31a1 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws.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. + +/*--- +description: Throws if a Temporal object with a calendar is supplied +esid: sec-temporal.plaindatetime.prototype.with +features: [Temporal] +---*/ + +const datetime = new Temporal.PlainDateTime(1976, 11, 18, 15, 23, 30, 123, 456, 789); + +const values = [ + Temporal.PlainDate.from("2022-04-12"), + Temporal.PlainDateTime.from("2022-04-12T15:19:45"), + Temporal.PlainMonthDay.from("04-12"), + Temporal.PlainTime.from("15:19:45"), + Temporal.PlainYearMonth.from("2022-04"), + Temporal.ZonedDateTime.from("2022-04-12T15:19:45[UTC]"), +]; + +for (const value of values) { + Object.defineProperty(value, "calendar", { + get() { throw new Test262Error("should not get calendar property") } + }); + Object.defineProperty(value, "timeZone", { + get() { throw new Test262Error("should not get timeZone property") } + }); + assert.throws( + TypeError, + () => datetime.with(value), + "throws with temporal object" + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-wrong-type.js new file mode 100644 index 00000000000..5c29d95e5e6 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/options-wrong-type.js @@ -0,0 +1,23 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.with +description: 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.PlainDateTime(2000, 5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ day: 5 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js index be6e0797b83..ce2bc34b9c6 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/order-of-operations.js @@ -42,6 +42,12 @@ const expected = [ "get year", "get year.valueOf", "call year.valueOf", + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", ]; const actual = []; const fields = { @@ -70,7 +76,13 @@ const argument = new Proxy(fields, { return key in target; }, }); -const result = instance.with(argument); +const options = { + get overflow() { + actual.push("get options.overflow"); + return TemporalHelpers.toPrimitiveObserver(actual, "constrain", "options.overflow"); + } +}; +const result = instance.with(argument, options); TemporalHelpers.assertPlainDateTime(result, 1, 1, "M01", 1, 1, 1, 1, 1, 1, 1); assert.sameValue(result.calendar.id, "iso8601", "calendar result"); assert.compareArray(actual, expected, "order of operations"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js index c23b9e9e970..4d3b05b0eac 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/with/overflow-invalid-string.js @@ -18,10 +18,12 @@ features: [Temporal] ---*/ const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12); -const badOverflows = ["", "CONSTRAIN", "balance", "other string"]; -badOverflows.forEach((overflow) => { + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { assert.throws( RangeError, () => datetime.with({ minute: 45 }, { overflow }), - `invalid overflow string (${overflow})`); -}); + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insufficient-data.js similarity index 100% rename from test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insuffcient-data.js rename to test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-object-insufficient-data.js diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-noniso.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-noniso.js new file mode 100644 index 00000000000..118282b48de --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-noniso.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate calendar is preserved with ISO PDT +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const cal = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { return "this is a string"; }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const pdt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0); +assert.sameValue(pdt.calendar.toString(), "iso8601", "PlainDateTime with ISO calendar"); +const pd = new Temporal.PlainDate(2010, 11, 12, cal); +const shifted = pdt.withPlainDate(pd); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is changed if receiver has ISO calendar (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal, + "calendar is changed if receiver has ISO calendar (2)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-id.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-id.js new file mode 100644 index 00000000000..28499059815 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-id.js @@ -0,0 +1,40 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate calendar is preserved when both calendars have the same id +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const cal1 = { + toString() { return "this is a string"; }, +}; +const cal2 = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { return "this is a string"; }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const pdt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal1); +const pd = new Temporal.PlainDate(2010, 11, 12, cal2); +const shifted = pdt.withPlainDate(pd); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is changed with same id (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal2, + "calendar is changed with same id (2)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-object.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-object.js new file mode 100644 index 00000000000..f963a3b61d2 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar-same-object.js @@ -0,0 +1,42 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: PlainDate calendar is preserved when both calendars are the same object +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +let calls = 0; +const cal = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { + ++calls; + return "this is a string"; + }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const pdt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); +const pd = new Temporal.PlainDate(2010, 11, 12, cal); +const shifted = pdt.withPlainDate(pd); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is unchanged with same calendars (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal, + "calendar is unchanged with same calendars (2)" +); +assert.sameValue(calls, 0, "should not have called cal.toString()"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar.js new file mode 100644 index 00000000000..ad9f56f7bb4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-plaindate-calendar.js @@ -0,0 +1,38 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: Original PDT calendar is preserved with ISO PlainDate +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const cal = { + id: 'thisisnotiso', + era() { return "the era"; }, + eraYear() { return 1909; }, + toString() { return "this is a string"; }, + year() { return 2008; }, + month() { return 9; }, + monthCode() { return "M09"; }, + day() { return 6; } +}; +const pdt = new Temporal.PlainDateTime(1995, 12, 7, 3, 24, 30, 0, 0, 0, cal); +const pd = new Temporal.PlainDate(2010, 11, 12); +assert.sameValue(pd.calendar.toString(), "iso8601", "PlainDate with ISO calendar"); +const shifted = pdt.withPlainDate(pd); + +TemporalHelpers.assertPlainDateTime( + shifted, + 2008, 9, "M09", 6, 3, 24, 30, 0, 0, 0, + "calendar is unchanged if input has ISO calendar (1)", + "the era", + 1909 +); + +assert.sameValue( + shifted.calendar, + cal, + "calendar is unchanged if input has ISO calendar (2)" +); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 00000000000..a4f4d9350f0 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js index 84f0ac12ef4..d86925d1b80 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/argument-string-iso-calendar.js @@ -3,7 +3,7 @@ /*--- esid: sec-temporal.plaindatetime.prototype.withplaindate -description: New calendar is preserved if original PDT has ISO calendar +description: Original PDT calendar is preserved with ISO string features: [Temporal] includes: [temporalHelpers.js] ---*/ diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..b67561e4829 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.withplaindate +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar); +instance.withPlainDate({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainMonthDay/calendar-always.js b/test/built-ins/Temporal/PlainMonthDay/calendar-always.js new file mode 100644 index 00000000000..8b9d87ff0a0 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/calendar-always.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pmd = new Temporal.PlainMonthDay(10, 31, "iso8601", 2019); + +assert.sameValue( + pmd.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPMD = Temporal.PlainMonthDay.from("2019-10-31"); // 2019 will get dropped + +assert.sameValue( + anotherPMD.toString({ calendarName: 'always' }), + "1972-10-31[u-ca=iso8601]", + "emit fallback year if calendarName = 'always' (static from)" +); diff --git a/test/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..aa302eb1aba --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/from/calendar-monthdayfromfields-called-with-options-undefined.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.plainmonthday.from +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +features: [Temporal] +---*/ + +const realMonthDayFromFields = Temporal.Calendar.prototype.monthDayFromFields; +let monthDayFromFieldsCallCount = 0; +Temporal.Calendar.prototype.monthDayFromFields = function (fields, options) { + monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return realMonthDayFromFields.call(this, fields, options); +} + +Temporal.PlainMonthDay.from("2000-05-02"); +assert.sameValue(monthDayFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.monthDayFromFields = realMonthDayFromFields; diff --git a/test/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js b/test/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js new file mode 100644 index 00000000000..c4c559bc6a8 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.PlainMonthDay.from({ monthCode: "M12", day: 15 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js index c2427006fdc..48ccf843643 100644 --- a/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainMonthDay/from/overflow-invalid-string.js @@ -27,6 +27,14 @@ const validValues = [ { monthCode: "M05", day: 2 }, "05-02", ]; -validValues.forEach((value) => { - assert.throws(RangeError, () => Temporal.PlainMonthDay.from(value, { overflow: "other string" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainMonthDay.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..649812219f9 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/equals/calendar-monthdayfromfields-called-with-options-undefined.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.plainmonthday.prototype.equals +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainMonthDay(5, 2, calendar); +instance.equals({ monthCode: "M05", day: 3, calendar }); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to monthDayFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realMonthDayFromFields = Temporal.Calendar.prototype.monthDayFromFields; +let monthDayFromFieldsCallCount = 0; +Temporal.Calendar.prototype.monthDayFromFields = function (fields, options) { + monthDayFromFieldsCallCount++; + assert.sameValue(options, undefined, "monthDayFromFields shouldn't be called with options"); + return realMonthDayFromFields.call(this, fields, options); +} + +instance.equals("2000-05-03"); +assert.sameValue(monthDayFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.monthDayFromFields = realMonthDayFromFields; diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js b/test/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..90b633fb299 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/toJSON/year-format.js @@ -0,0 +1,55 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +// For PlainMonthDay, the ISO reference year is only present in the string if +// the calendar is not ISO 8601 +class NotISO extends Temporal.Calendar { + constructor() { super("iso8601"); } + toString() { return "not-iso"; } +} +const calendar = new NotISO(); + +let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000); +assert.sameValue(instance.toJSON(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000); +assert.sameValue(instance.toJSON(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999); +assert.sameValue(instance.toJSON(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000); +assert.sameValue(instance.toJSON(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(10, 9, calendar, -999); +assert.sameValue(instance.toJSON(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 7, calendar, -1); +assert.sameValue(instance.toJSON(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 5, calendar, 0); +assert.sameValue(instance.toJSON(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 3, calendar, 1); +assert.sameValue(instance.toJSON(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(2, 10, calendar, 999); +assert.sameValue(instance.toJSON(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000); +assert.sameValue(instance.toJSON(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999); +assert.sameValue(instance.toJSON(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000); +assert.sameValue(instance.toJSON(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000); +assert.sameValue(instance.toJSON(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js index fadff8929f4..4d1d85b6797 100644 --- a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/calendarname-always.js @@ -8,9 +8,9 @@ features: [Temporal] ---*/ const tests = [ - [[], "05-02[u-ca=iso8601]"], + [[], "1972-05-02[u-ca=iso8601]"], [[{ toString() { return "custom"; } }], "1972-05-02[u-ca=custom]"], - [[{ toString() { return "iso8601"; } }], "05-02[u-ca=iso8601]"], + [[{ toString() { return "iso8601"; } }], "1972-05-02[u-ca=iso8601]"], [[{ toString() { return "ISO8601"; } }], "1972-05-02[u-ca=ISO8601]"], [[{ toString() { return "\u0131so8601"; } }], "1972-05-02[u-ca=\u0131so8601]"], // dotless i ]; diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..67575fe09f8 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/options-wrong-type.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.plainmonthday.prototype.tostring +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.PlainMonthDay(5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js new file mode 100644 index 00000000000..3898ff66b65 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/toString/year-format.js @@ -0,0 +1,55 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainmonthday.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +// For PlainMonthDay, the ISO reference year is only present in the string if +// the calendar is not ISO 8601 +class NotISO extends Temporal.Calendar { + constructor() { super("iso8601"); } + toString() { return "not-iso"; } +} +const calendar = new NotISO(); + +let instance = new Temporal.PlainMonthDay(12, 3, calendar, -100000); +assert.sameValue(instance.toString(), "-100000-12-03[u-ca=not-iso]", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, -10000); +assert.sameValue(instance.toString(), "-010000-04-05[u-ca=not-iso]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, -9999); +assert.sameValue(instance.toString(), "-009999-06-07[u-ca=not-iso]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, -1000); +assert.sameValue(instance.toString(), "-001000-08-09[u-ca=not-iso]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(10, 9, calendar, -999); +assert.sameValue(instance.toString(), "-000999-10-09[u-ca=not-iso]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 7, calendar, -1); +assert.sameValue(instance.toString(), "-000001-08-07[u-ca=not-iso]", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(6, 5, calendar, 0); +assert.sameValue(instance.toString(), "0000-06-05[u-ca=not-iso]", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 3, calendar, 1); +assert.sameValue(instance.toString(), "0001-04-03[u-ca=not-iso]", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(2, 10, calendar, 999); +assert.sameValue(instance.toString(), "0999-02-10[u-ca=not-iso]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(1, 23, calendar, 1000); +assert.sameValue(instance.toString(), "1000-01-23[u-ca=not-iso]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(4, 5, calendar, 9999); +assert.sameValue(instance.toString(), "9999-04-05[u-ca=not-iso]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainMonthDay(6, 7, calendar, 10000); +assert.sameValue(instance.toString(), "+010000-06-07[u-ca=not-iso]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainMonthDay(8, 9, calendar, 100000); +assert.sameValue(instance.toString(), "+100000-08-09[u-ca=not-iso]", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.js new file mode 100644 index 00000000000..5dbd34864b0 --- /dev/null +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/with/options-wrong-type.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.plainmonthday.prototype.with +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.PlainMonthDay(5, 2); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ day: 5 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js index 5ed47e97538..0036dfe6380 100644 --- a/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainMonthDay/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const monthday = new Temporal.PlainMonthDay(5, 2); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => monthday.with({ day: 8 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => monthday.with({ day: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainTime/from/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js similarity index 100% rename from test/built-ins/Temporal/PlainTime/from/argument-string-invalid.js rename to test/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js diff --git a/test/built-ins/Temporal/PlainTime/from/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/from/options-wrong-type.js new file mode 100644 index 00000000000..587674dd128 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.PlainTime.from({ hour: 12, minute: 34 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js index 856d071453e..dcefde8a682 100644 --- a/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js @@ -19,8 +19,14 @@ const validValues = [ { hour: 12 }, "12:00", ]; -validValues.forEach((value) => { - ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"].forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainTime.from(value, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js new file mode 100644 index 00000000000..2edf4591a14 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/round/options-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-temporal.plaintime.prototype.round +description: TypeError thrown when options argument is missing or a non-string primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainTime(); +assert.throws(TypeError, () => instance.round(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.round(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js index 1da2034e113..917a5a409d2 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js @@ -8,7 +8,28 @@ features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); -const values = ["era", "year", "month", "week", "day", "years", "months", "weeks", "days", "nonsense", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => time.round({ smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => time.round({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js index f74105aba51..0faa16156a0 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..f48b7c373bc --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.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.plaintime.prototype.since +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.PlainTime(); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.PlainTime(12, 34, 56), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js index de440191cf2..b375626bf59 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js new file mode 100644 index 00000000000..768f1dba079 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..5a594f23a42 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.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.plaintime.prototype.toplaindatetime +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321, calendar); +instance.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js index 2bff43e90a7..2c90ffaa47a 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js @@ -7,13 +7,17 @@ description: auto value for fractionalSecondDigits option features: [Temporal] ---*/ +const zeroSeconds = new Temporal.PlainTime(15, 23); +const wholeSeconds = new Temporal.PlainTime(15, 23, 30); +const subSeconds = new Temporal.PlainTime(15, 23, 30, 123, 400); + const tests = [ - ["15:23", "15:23:00"], - ["15:23:30", "15:23:30"], - ["15:23:30.1234", "15:23:30.1234"], + [zeroSeconds, "15:23:00"], + [wholeSeconds, "15:23:30"], + [subSeconds, "15:23:30.1234"], ]; -for (const [input, expected] of tests) { - const plainTime = Temporal.PlainTime.from(input); - assert.sameValue(plainTime.toString({ fractionalSecondDigits: "auto" }), expected); +for (const [time, expected] of tests) { + assert.sameValue(time.toString(), expected, "default is to emit seconds and drop trailing zeroes"); + assert.sameValue(time.toString({ fractionalSecondDigits: "auto" }), expected, "auto is the default"); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js index 3d4ab17c430..1be21d324c7 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -10,12 +10,13 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaintime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); -for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos"]) { - assert.throws(RangeError, () => time.toString({ fractionalSecondDigits })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos", "auto\0"]) { + assert.throws(RangeError, () => time.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js index 9b7c5250e0d..3ca8fed5aa0 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -10,7 +10,7 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaintime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js index 5973c534001..0ea1eb838ea 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js @@ -7,16 +7,27 @@ description: Number for fractionalSecondDigits option features: [Temporal] ---*/ -const t1 = Temporal.PlainTime.from("15:23"); -const t2 = Temporal.PlainTime.from("15:23:30"); -const t3 = Temporal.PlainTime.from("15:23:30.1234"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 0 }), "15:23:30"); -assert.sameValue(t1.toString({ fractionalSecondDigits: 2 }), "15:23:00.00"); -assert.sameValue(t2.toString({ fractionalSecondDigits: 2 }), "15:23:30.00"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 2 }), "15:23:30.12"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 3 }), "15:23:30.123"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 6 }), "15:23:30.123400"); -assert.sameValue(t1.toString({ fractionalSecondDigits: 7 }), "15:23:00.0000000"); -assert.sameValue(t2.toString({ fractionalSecondDigits: 7 }), "15:23:30.0000000"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 7 }), "15:23:30.1234000"); -assert.sameValue(t3.toString({ fractionalSecondDigits: 9 }), "15:23:30.123400000"); +const zeroSeconds = new Temporal.PlainTime(15, 23); +const wholeSeconds = new Temporal.PlainTime(15, 23, 30); +const subSeconds = new Temporal.PlainTime(15, 23, 30, 123, 400); + +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 0 }), "15:23:30", + "truncates 4 decimal places to 0"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 2 }), "15:23:00.00", + "pads zero seconds to 2 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 2 }), "15:23:30.00", + "pads whole seconds to 2 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 2 }), "15:23:30.12", + "truncates 4 decimal places to 2"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 3 }), "15:23:30.123", + "truncates 4 decimal places to 3"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 6 }), "15:23:30.123400", + "pads 4 decimal places to 6"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 7 }), "15:23:00.0000000", + "pads zero seconds to 7 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 7 }), "15:23:30.0000000", + "pads whole seconds to 7 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 7 }), "15:23:30.1234000", + "pads 4 decimal places to 7"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 9 }), "15:23:30.123400000", + "pads 4 decimal places to 9"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js index 5959dd94591..1d6e899312f 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -10,13 +10,17 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaintime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); -assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -Infinity })); -assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -1 })); -assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: 10 })); -assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: Infinity })); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -Infinity }), + "−∞ is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: -1 }), + "−1 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: 10 }), + "10 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: Infinity }), + "∞ is out of range for fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js index 1d9d2dff038..6c33c55f7f4 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js @@ -8,29 +8,31 @@ info: | sec-getoption step 3: 3. If _value_ is *undefined*, return _fallback_. sec-getstringornumberoption step 2: - 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.plaintime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ +const zeroSeconds = new Temporal.PlainTime(15, 23); +const wholeSeconds = new Temporal.PlainTime(15, 23, 30); +const subSeconds = new Temporal.PlainTime(15, 23, 30, 123, 400); + const tests = [ - ["15:23", "15:23:00"], - ["15:23:30", "15:23:30"], - ["15:23:30.1234", "15:23:30.1234"], + [zeroSeconds, "15:23:00"], + [wholeSeconds, "15:23:30"], + [subSeconds, "15:23:30.1234"], ]; -for (const [input, expected] of tests) { - const time = Temporal.PlainTime.from(input); - +for (const [time, expected] of tests) { const explicit = time.toString({ fractionalSecondDigits: undefined }); - assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto"); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); const implicit = time.toString({}); - assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto"); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); const lambda = time.toString(() => {}); - assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto"); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js index 54440155aa3..79fcd282938 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -22,4 +22,26 @@ features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); -TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(time); + +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: null }), + "null is not a number and converts to the string 'null' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: true }), + "true is not a number and converts to the string 'true' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: false }), + "false is not a number and converts to the string 'false' which is not valid for fractionalSecondDigits"); +assert.throws(TypeError, () => time.toString({ fractionalSecondDigits: Symbol() }), + "symbols are not numbers and cannot convert to strings"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: 2n }), + "bigints are not numbers and convert to strings which are not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: {} }), + "plain objects are not numbers and convert to strings which are not valid for fractionalSecondDigits"); + +const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); +const result = time.toString({ fractionalSecondDigits: observer }); +assert.sameValue(result, "12:34:56.98765", "object with toString uses toString return value"); +assert.compareArray(actual, expected, "object with toString calls toString and not valueOf"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..d77abfa038d --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.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.plaintime.prototype.tostring +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.PlainTime(); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js b/test/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js index 4c67d223aac..d580f6f5e23 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js @@ -7,7 +7,7 @@ description: Rounding can cross midnight features: [Temporal] ---*/ -const plainTime = Temporal.PlainTime.from("23:59:59.999999999"); +const plainTime = new Temporal.PlainTime(23, 59, 59, 999, 999, 999); // one nanosecond before 00:00:00 for (const roundingMode of ["ceil", "halfExpand"]) { assert.sameValue(plainTime.toString({ fractionalSecondDigits: 8, roundingMode }), "00:00:00.00000000"); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js index 4f6552b87be..97006c66ff6 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js @@ -10,10 +10,28 @@ features: [Temporal] const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); -assert.sameValue(result1, "12:34:56.123988", "roundingMode is ceil"); +assert.sameValue(result1, "12:34:56.123988", + "roundingMode is ceil (with 6 digits from smallestUnit)"); -const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); -assert.sameValue(result2, "12:34:56.124", "roundingMode is ceil"); +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "ceil" }); +assert.sameValue(result2, "12:34:56.123988", + "roundingMode is ceil (with 6 digits from fractionalSecondDigits)"); -const result3 = time.toString({ smallestUnit: "second", roundingMode: "ceil" }); -assert.sameValue(result3, "12:34:57", "roundingMode is ceil"); +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is ceil (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "ceil" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is ceil (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result5, "12:34:57", + "roundingMode is ceil (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "ceil" }); +assert.sameValue(result6, "12:34:57", + "roundingMode is ceil (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "ceil" }); +assert.sameValue(result7, "12:35", "roundingMode is ceil (round to minute)"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js index 63b30d3cc5b..528d8cd0c84 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js @@ -10,10 +10,28 @@ features: [Temporal] const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); -assert.sameValue(result1, "12:34:56.123987", "roundingMode is floor"); +assert.sameValue(result1, "12:34:56.123987", + "roundingMode is floor (with 6 digits from smallestUnit)"); -const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); -assert.sameValue(result2, "12:34:56.123", "roundingMode is floor"); +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "floor" }); +assert.sameValue(result2, "12:34:56.123987", + "roundingMode is floor (with 6 digits from fractionalSecondDigits)"); -const result3 = time.toString({ smallestUnit: "second", roundingMode: "floor" }); -assert.sameValue(result3, "12:34:56", "roundingMode is floor"); +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result3, "12:34:56.123", + "roundingMode is floor (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "floor" }); +assert.sameValue(result4, "12:34:56.123", + "roundingMode is floor (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is floor (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "floor" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is floor (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "floor" }); +assert.sameValue(result7, "12:34", "roundingMode is floor (round to minute)"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js index cd7b8e4673a..35a65a86665 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js @@ -10,10 +10,28 @@ features: [Temporal] const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); -assert.sameValue(result1, "12:34:56.123988", "roundingMode is halfExpand"); +assert.sameValue(result1, "12:34:56.123988", + "roundingMode is halfExpand (with 6 digits from smallestUnit)"); -const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); -assert.sameValue(result2, "12:34:56.124", "roundingMode is halfExpand"); +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "halfExpand" }); +assert.sameValue(result2, "12:34:56.123988", + "roundingMode is halfExpand (with 6 digits from fractionalSecondDigits)"); -const result3 = time.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); -assert.sameValue(result3, "12:34:56", "roundingMode is halfExpand"); +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is halfExpand (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "halfExpand" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is halfExpand (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is halfExpand (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "halfExpand" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is halfExpand (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "halfExpand" }); +assert.sameValue(result7, "12:35", "roundingMode is halfExpand (round to minute)"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js index e25101caf42..d3496b266bd 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js @@ -10,10 +10,28 @@ features: [Temporal] const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); -assert.sameValue(result1, "12:34:56.123987", "roundingMode is trunc"); +assert.sameValue(result1, "12:34:56.123987", + "roundingMode is trunc (with 6 digits from smallestUnit)"); -const result2 = time.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); -assert.sameValue(result2, "12:34:56.123", "roundingMode is trunc"); +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "trunc" }); +assert.sameValue(result2, "12:34:56.123987", + "roundingMode is trunc (with 6 digits from fractionalSecondDigits)"); -const result3 = time.toString({ smallestUnit: "second", roundingMode: "trunc" }); -assert.sameValue(result3, "12:34:56", "roundingMode is trunc"); +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result3, "12:34:56.123", + "roundingMode is trunc (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "trunc" }); +assert.sameValue(result4, "12:34:56.123", + "roundingMode is trunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is trunc (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "trunc" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is trunc (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "trunc" }); +assert.sameValue(result7, "12:34", "roundingMode is trunc (round to minute)"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js index 06ab3baac63..318041efa06 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js @@ -21,11 +21,10 @@ for (const [smallestUnit, expected] of tests) { smallestUnit, get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } }); - assert.sameValue(string, expected, smallestUnit); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); } assert.throws(RangeError, () => time.toString({ smallestUnit: "hour", get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } -})); - +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js index d5ea0a7b3e7..d093928a489 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js @@ -8,6 +8,30 @@ features: [Temporal] ---*/ const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); -for (const smallestUnit of ["era", "year", "month", "day", "hour", "nonsense", "other string", "m\u0131nute", "SECOND"]) { - assert.throws(RangeError, () => time.toString({ smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "hour", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "hours", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => time.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js index e2b4c71dbd2..bb942179e2c 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js +++ b/test/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js @@ -7,21 +7,41 @@ description: Valid units for the smallestUnit option features: [Temporal] ---*/ -const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); -assert.sameValue(time.toString({ smallestUnit: "minute" }), "12:34"); -assert.sameValue(time.toString({ smallestUnit: "second" }), "12:34:56"); -assert.sameValue(time.toString({ smallestUnit: "millisecond" }), "12:34:56.789"); -assert.sameValue(time.toString({ smallestUnit: "microsecond" }), "12:34:56.789999"); -assert.sameValue(time.toString({ smallestUnit: "nanosecond" }), "12:34:56.789999999"); +const time = new Temporal.PlainTime(12, 34, 56, 123, 456, 789); -const time2 = new Temporal.PlainTime(12, 34); -assert.sameValue(time2.toString({ smallestUnit: "minute" }), "12:34"); -assert.sameValue(time2.toString({ smallestUnit: "second" }), "12:34:00"); -assert.sameValue(time2.toString({ smallestUnit: "millisecond" }), "12:34:00.000"); -assert.sameValue(time2.toString({ smallestUnit: "microsecond" }), "12:34:00.000000"); -assert.sameValue(time2.toString({ smallestUnit: "nanosecond" }), "12:34:00.000000000"); +function test(instance, expectations, description) { + for (const [smallestUnit, expectedResult] of expectations) { + assert.sameValue(instance.toString({ smallestUnit }), expectedResult, + `${description} with smallestUnit "${smallestUnit}"`); + } +} + +test( + time, + [ + ["minute", "12:34"], + ["second", "12:34:56"], + ["millisecond", "12:34:56.123"], + ["microsecond", "12:34:56.123456"], + ["nanosecond", "12:34:56.123456789"], + ], + "subseconds toString" +); + +test( + new Temporal.PlainTime(12, 34), + [ + ["minute", "12:34"], + ["second", "12:34:00"], + ["millisecond", "12:34:00.000"], + ["microsecond", "12:34:00.000000"], + ["nanosecond", "12:34:00.000000000"], + ], + "whole minutes toString" +); const notValid = [ + "era", "year", "month", "week", @@ -30,5 +50,6 @@ const notValid = [ ]; notValid.forEach((smallestUnit) => { - assert.throws(RangeError, () => time.toString({ smallestUnit }), smallestUnit); + assert.throws(RangeError, () => time.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); }); diff --git a/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js new file mode 100644 index 00000000000..03b196269e8 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg }), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..e6b9fc3e122 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.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.plaintime.prototype.tozoneddatetime +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321, calendar); +instance.toZonedDateTime({ plainDate: { year: 2000, month: 5, day: 3, calendar }, timeZone: new Temporal.TimeZone("UTC") }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js index 7fcf10a557b..ff95f0e7832 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..4f30cb995d2 --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.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.plaintime.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainTime(); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.PlainTime(12, 34, 56), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js index 7225494a217..62ca4957d27 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,28 @@ features: [Temporal] const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); -const values = ["era", "eraYear", "years", "months", "weeks", "days", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js new file mode 100644 index 00000000000..d45bbc8986d --- /dev/null +++ b/test/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.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.plaintime.prototype.with +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.PlainTime(); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ minute: 45 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js index 796cec5fcf3..dc50e7795bc 100644 --- a/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js @@ -16,6 +16,12 @@ features: [Temporal] const time = new Temporal.PlainTime(12); const values = ["", "CONSTRAIN", "balance", "other string"]; -for (const overflow of values) { - assert.throws(RangeError, () => time.with({ minute: 45 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => time.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/calendar-always.js b/test/built-ins/Temporal/PlainYearMonth/calendar-always.js new file mode 100644 index 00000000000..0aad58df09f --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/calendar-always.js @@ -0,0 +1,24 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth +description: If calendar name is to be emitted, include additional reference info +features: [Temporal] +---*/ + +const pym = new Temporal.PlainYearMonth(2019, 10, "iso8601", 31); + +assert.sameValue( + pym.toString({ calendarName: 'always' }), + "2019-10-31[u-ca=iso8601]", + "emit year-month-day if calendarName = 'always' (four-argument constructor)" +); + +const anotherPYM = Temporal.PlainYearMonth.from("2019-10-31"); // 31 will get dropped + +assert.sameValue( + anotherPYM.toString({ calendarName: 'always' }), + "2019-10-01[u-ca=iso8601]", + "emit fallback day if calendarName = 'always' (static from)" +); diff --git a/test/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..999e5afa760 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/compare/calendar-yearmonthfromfields-called-with-options-undefined.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.plainyearmonth.compare +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +Temporal.PlainYearMonth.compare({ year: 2000, month: 5, calendar }, { year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 2); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +Temporal.PlainYearMonth.compare("2000-05-01", "2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 2); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; diff --git a/test/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..f3f33f1ba0f --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/from/calendar-yearmonthfromfields-called-with-options-undefined.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.plainyearmonth.from +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +features: [Temporal] +---*/ + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +Temporal.PlainYearMonth.from("2000-05-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; diff --git a/test/built-ins/Temporal/PlainYearMonth/from/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/from/options-wrong-type.js new file mode 100644 index 00000000000..eb85b8180b3 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.PlainYearMonth.from({ year: 2021, monthCode: "M01" }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js index d30774eece5..11335f2481a 100644 --- a/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/from/overflow-invalid-string.js @@ -27,8 +27,14 @@ const validValues = [ { year: 2000, month: 5 }, "2000-05", ]; -validValues.forEach((value) => { - ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"].forEach((overflow) => { - assert.throws(RangeError, () => Temporal.PlainYearMonth.from(value, { overflow })); - }); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.PlainYearMonth.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js b/test/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js new file mode 100644 index 00000000000..de0bee72b0f --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/add/calendar-datefromfields-called.js @@ -0,0 +1,147 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.add +description: > + Calls calendar's dateFromFields method to obtain a start date for the + operation, based on the sign of the duration +info: | + 8. Let _fields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»). + 9. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0). + 10. If _sign_ < 0, then + a. Let _dayFromCalendar_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_). + b. Let _day_ be ? ToPositiveInteger(_dayFromCalendar_). + 11. Else, + a. Let _day_ be 1. + 12. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, _day_). + 13. Let _date_ be ? DateFromFields(_calendar_, _fields_, *undefined*). +includes: [deepEqual.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCalls = []; + } + year(date) { + // years in this calendar start and end on the same day as ISO 8601 years + return date.getISOFields().isoYear; + } + month(date) { + // this calendar has 10 months of 36 days each, plus an 11th month of 5 or 6 + const { isoYear, isoMonth, isoDay } = date.getISOFields(); + const isoDate = new Temporal.PlainDate(isoYear, isoMonth, isoDay); + return Math.floor((isoDate.dayOfYear - 1) / 36) + 1; + } + monthCode(date) { + return "M" + this.month(date).toString().padStart(2, "0"); + } + day(date) { + return (date.dayOfYear - 1) % 36 + 1; + } + daysInMonth(date) { + if (this.month(date) < 11) return 36; + return this.daysInYear(date) - 360; + } + _dateFromFieldsImpl({ year, month, monthCode, day }) { + if (year === undefined) throw new TypeError("year required"); + if (month === undefined && monthCode === undefined) throw new TypeError("one of month or monthCode required"); + if (month !== undefined && month < 1) throw new RangeError("month < 1"); + if (day === undefined) throw new TypeError("day required"); + + if (monthCode !== undefined) { + const numberPart = +(monthCode.slice(1)); + if ("M" + `${numberPart}`.padStart(2, "0") !== monthCode) throw new RangeError("invalid monthCode"); + if (month === undefined) { + month = numberPart; + } else if (month !== numberPart) { + throw new RangeError("month and monthCode must match"); + } + } + + const isoDayOfYear = (month - 1) * 36 + day; + return new Temporal.PlainDate(year, 1, 1).add({ days: isoDayOfYear - 1 }).withCalendar(this); + } + dateFromFields(...args) { + this.dateFromFieldsCalls.push(args); + return this._dateFromFieldsImpl(...args); + } + yearMonthFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, day: 1 }, options).getISOFields(); + return new Temporal.PlainYearMonth(isoYear, isoMonth, this, isoDay); + } + monthDayFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, year: 2000 }, options).getISOFields(); + return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear); + } + dateAdd(date, duration, options) { + if (duration.months) throw new Error("adding months not implemented in this test"); + return super.dateAdd(date, duration, options); + } + toString() { + return "thirty-six"; + } +} + +const calendar = new CustomCalendar(); +const month2 = Temporal.PlainYearMonth.from({ year: 2022, month: 2, calendar }); +const lessThanOneMonth = new Temporal.Duration(0, 0, 0, 35); +const oneMonth = new Temporal.Duration(0, 0, 0, 36); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(lessThanOneMonth), + 2022, 2, "M02", + "adding positive less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when adding positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(oneMonth), + 2022, 3, "M03", + "adding positive one month's worth of days yields the following month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when adding positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(lessThanOneMonth.negated()), + 2022, 2, "M02", + "adding negative less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when adding negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.add(oneMonth.negated()), + 2022, 1, "M01", + "adding negative one month's worth of days yields the previous month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when adding negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/add/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/add/options-wrong-type.js new file mode 100644 index 00000000000..95d62d106b2 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/add/options-wrong-type.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.plainyearmonth.prototype.add +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.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.add({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js index 4913de46a29..1633f1b6544 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/add/overflow-invalid-string.js @@ -20,6 +20,12 @@ features: [Temporal] const yearmonth = new Temporal.PlainYearMonth(2000, 5); const duration = new Temporal.Duration(1, 1); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.add(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..490c35f4939 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/equals/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.equals +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.equals({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.equals("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..d7978361ad5 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-datefromfields-called-with-options-undefined.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.plainyearmonth.prototype.since +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..db48db0cfaa --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.since +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.since("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js index 09b7687f263..00a668d252d 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,34 @@ features: [Temporal] const earlier = new Temporal.PlainYearMonth(2000, 5); const later = new Temporal.PlainYearMonth(2001, 6); -const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..9441a8e4dba --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/options-wrong-type.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.plainyearmonth.prototype.since +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.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.PlainYearMonth(1976, 11), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js index 21b0c4b6983..f8e1f541a06 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,34 @@ features: [Temporal] const earlier = new Temporal.PlainYearMonth(2000, 5); const later = new Temporal.PlainYearMonth(2001, 6); -const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js new file mode 100644 index 00000000000..7e717222a8d --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/calendar-datefromfields-called.js @@ -0,0 +1,147 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.subtract +description: > + Calls calendar's dateFromFields method to obtain a start date for the + operation, based on the sign of the duration +info: | + 9. Let _fields_ be ? PrepareTemporalFields(_yearMonth_, _fieldNames_, «»). + 10. Let _sign_ be ! DurationSign(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], 0, 0, 0, 0, 0, 0). + 11. If _sign_ < 0, then + a. Let _dayFromCalendar_ be ? CalendarDaysInMonth(_calendar_, _yearMonth_). + b. Let _day_ be ? ToPositiveInteger(_dayFromCalendar_). + 12. Else, + a. Let _day_ be 1. + 13. Perform ! CreateDataPropertyOrThrow(_fields_, *"day"*, _day_). + 14. Let _date_ be ? DateFromFields(_calendar_, _fields_, *undefined*). +includes: [deepEqual.js, temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomCalendar extends Temporal.Calendar { + constructor() { + super("iso8601"); + this.dateFromFieldsCalls = []; + } + year(date) { + // years in this calendar start and end on the same day as ISO 8601 years + return date.getISOFields().isoYear; + } + month(date) { + // this calendar has 10 months of 36 days each, plus an 11th month of 5 or 6 + const { isoYear, isoMonth, isoDay } = date.getISOFields(); + const isoDate = new Temporal.PlainDate(isoYear, isoMonth, isoDay); + return Math.floor((isoDate.dayOfYear - 1) / 36) + 1; + } + monthCode(date) { + return "M" + this.month(date).toString().padStart(2, "0"); + } + day(date) { + return (date.dayOfYear - 1) % 36 + 1; + } + daysInMonth(date) { + if (this.month(date) < 11) return 36; + return this.daysInYear(date) - 360; + } + _dateFromFieldsImpl({ year, month, monthCode, day }) { + if (year === undefined) throw new TypeError("year required"); + if (month === undefined && monthCode === undefined) throw new TypeError("one of month or monthCode required"); + if (month !== undefined && month < 1) throw new RangeError("month < 1"); + if (day === undefined) throw new TypeError("day required"); + + if (monthCode !== undefined) { + const numberPart = +(monthCode.slice(1)); + if ("M" + `${numberPart}`.padStart(2, "0") !== monthCode) throw new RangeError("invalid monthCode"); + if (month === undefined) { + month = numberPart; + } else if (month !== numberPart) { + throw new RangeError("month and monthCode must match"); + } + } + + const isoDayOfYear = (month - 1) * 36 + day; + return new Temporal.PlainDate(year, 1, 1).add({ days: isoDayOfYear - 1 }).withCalendar(this); + } + dateFromFields(...args) { + this.dateFromFieldsCalls.push(args); + return this._dateFromFieldsImpl(...args); + } + yearMonthFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, day: 1 }, options).getISOFields(); + return new Temporal.PlainYearMonth(isoYear, isoMonth, this, isoDay); + } + monthDayFromFields(fields, options) { + const { isoYear, isoMonth, isoDay } = this._dateFromFieldsImpl({ ...fields, year: 2000 }, options).getISOFields(); + return new Temporal.PlainMonthDay(isoMonth, isoDay, this, isoYear); + } + dateAdd(date, duration, options) { + if (duration.months) throw new Error("adding months not implemented in this test"); + return super.dateAdd(date, duration, options); + } + toString() { + return "thirty-six"; + } +} + +const calendar = new CustomCalendar(); +const month2 = Temporal.PlainYearMonth.from({ year: 2022, month: 2, calendar }); +const lessThanOneMonth = new Temporal.Duration(0, 0, 0, 35); +const oneMonth = new Temporal.Duration(0, 0, 0, 36); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(lessThanOneMonth), + 2022, 2, "M02", + "subtracting positive less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when subtracting positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(oneMonth), + 2022, 1, "M01", + "subtracting positive one month's worth of days yields the previous month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 36 }, + "last day of month 2 passed to dateFromFields when subtracting positive duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(lessThanOneMonth.negated()), + 2022, 2, "M02", + "subtracting negative less than one month's worth of days yields the same month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when subtracting negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); + +calendar.dateFromFieldsCalls = []; +TemporalHelpers.assertPlainYearMonth( + month2.subtract(oneMonth.negated()), + 2022, 3, "M03", + "subtracting negative one month's worth of days yields the following month" +); +assert.sameValue(calendar.dateFromFieldsCalls.length, 1, "dateFromFields was called"); +assert.deepEqual( + calendar.dateFromFieldsCalls[0][0], + { year: 2022, month: 2, monthCode: "M02", day: 1 }, + "first day of month 2 passed to dateFromFields when subtracting negative duration" +); +assert.sameValue(calendar.dateFromFieldsCalls[0][1], undefined, "undefined options passed"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-wrong-type.js new file mode 100644 index 00000000000..d64177826d6 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/options-wrong-type.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.plainyearmonth.prototype.subtract +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.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.subtract({ months: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js index 8c2efb855a7..46286d5a6a2 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/subtract/overflow-invalid-string.js @@ -20,6 +20,12 @@ features: [Temporal] const yearmonth = new Temporal.PlainYearMonth(2000, 5); const duration = new Temporal.Duration(1, 1); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.subtract(duration, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js b/test/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..706d3624a0f --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/toJSON/year-format.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.plainyearmonth.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainYearMonth(-100000, 12); +assert.sameValue(instance.toJSON(), "-100000-12", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-10000, 4); +assert.sameValue(instance.toJSON(), "-010000-04", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-9999, 6); +assert.sameValue(instance.toJSON(), "-009999-06", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1000, 8); +assert.sameValue(instance.toJSON(), "-001000-08", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-999, 10); +assert.sameValue(instance.toJSON(), "-000999-10", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1, 8); +assert.sameValue(instance.toJSON(), "-000001-08", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(0, 6); +assert.sameValue(instance.toJSON(), "0000-06", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1, 4); +assert.sameValue(instance.toJSON(), "0001-04", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(999, 2); +assert.sameValue(instance.toJSON(), "0999-02", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1000, 1); +assert.sameValue(instance.toJSON(), "1000-01", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(9999, 4); +assert.sameValue(instance.toJSON(), "9999-04", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(10000, 6); +assert.sameValue(instance.toJSON(), "+010000-06", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(100000, 8); +assert.sameValue(instance.toJSON(), "+100000-08", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js index d6fa52e1064..be8cc7e93f8 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/calendarname-always.js @@ -14,7 +14,7 @@ const yearmonth1 = new Temporal.PlainYearMonth(2000, 5); const yearmonth2 = new Temporal.PlainYearMonth(2000, 5, calendar); [ - [yearmonth1, "2000-05[u-ca=iso8601]"], + [yearmonth1, "2000-05-01[u-ca=iso8601]"], // fallback day 1 used [yearmonth2, "2000-05-01[u-ca=custom]"], ].forEach(([yearmonth, expected]) => { const result = yearmonth.toString({ calendarName: "always" }); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..1e759554d51 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/options-wrong-type.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.plainyearmonth.prototype.tostring +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.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.js new file mode 100644 index 00000000000..6c1b9474638 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/toString/year-format.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.plainyearmonth.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +let instance = new Temporal.PlainYearMonth(-100000, 12); +assert.sameValue(instance.toString(), "-100000-12", "large negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-10000, 4); +assert.sameValue(instance.toString(), "-010000-04", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-9999, 6); +assert.sameValue(instance.toString(), "-009999-06", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1000, 8); +assert.sameValue(instance.toString(), "-001000-08", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-999, 10); +assert.sameValue(instance.toString(), "-000999-10", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(-1, 8); +assert.sameValue(instance.toString(), "-000001-08", "year -1 formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(0, 6); +assert.sameValue(instance.toString(), "0000-06", "year 0 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1, 4); +assert.sameValue(instance.toString(), "0001-04", "year 1 formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(999, 2); +assert.sameValue(instance.toString(), "0999-02", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(1000, 1); +assert.sameValue(instance.toString(), "1000-01", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(9999, 4); +assert.sameValue(instance.toString(), "9999-04", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.PlainYearMonth(10000, 6); +assert.sameValue(instance.toString(), "+010000-06", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.PlainYearMonth(100000, 8); +assert.sameValue(instance.toString(), "+100000-08", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..89bdacd0cd3 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-datefromfields-called-with-options-undefined.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.plainyearmonth.prototype.until +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 2); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..d9b946e2795 --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/calendar-yearmonthfromfields-called-with-options-undefined.js @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plainyearmonth.prototype.until +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +let instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until({ year: 2000, month: 6, calendar }); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); + +// Test again, but overriding the global Temporal.Calendar.prototype method so +// we can observe the call to yearMonthFromFields() on the ISO8601 calendar +// that occurs when we parse the string + +const realYearMonthFromFields = Temporal.Calendar.prototype.yearMonthFromFields; +let yearMonthFromFieldsCallCount = 0; +Temporal.Calendar.prototype.yearMonthFromFields = function (fields, options) { + yearMonthFromFieldsCallCount++; + assert.sameValue(options, undefined, "yearMonthFromFields shouldn't be called with options"); + return realYearMonthFromFields.call(this, fields, options); +} + +calendar = new Temporal.Calendar("iso8601"); +instance = new Temporal.PlainYearMonth(2000, 5, calendar); +instance.until("2000-06-01"); +assert.sameValue(yearMonthFromFieldsCallCount, 1); + +Temporal.Calendar.prototype.yearMonthFromFields = realYearMonthFromFields; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js index bb243a89914..e3055ec8c49 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,34 @@ features: [Temporal] const earlier = new Temporal.PlainYearMonth(2000, 5); const later = new Temporal.PlainYearMonth(2001, 6); -const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..ff3266edccc --- /dev/null +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/options-wrong-type.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.plainyearmonth.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.PlainYearMonth(1976, 11), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js index 9e494305079..07095eaf3f4 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,34 @@ features: [Temporal] const earlier = new Temporal.PlainYearMonth(2000, 5); const later = new Temporal.PlainYearMonth(2001, 6); -const values = ["era", "eraYear", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "week", + "day", + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", + "month\0", + "YEAR", + "eras", + "eraYears", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", + "months\0", + "YEARS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js index bc8f0a542ec..8b6b6e1af38 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/with/options-wrong-type.js @@ -7,7 +7,7 @@ description: TypeError thrown when options argument is a primitive features: [BigInt, Symbol, Temporal] ---*/ -const values = [ +const badOptions = [ null, true, "2021-01", @@ -16,7 +16,8 @@ const values = [ 2n, ]; -const ym = Temporal.PlainYearMonth.from("2019-10"); -values.forEach((value) => { - assert.throws(TypeError, () => ym.with({ year: 2020 }, value), `TypeError on wrong argument type ${typeof value}`); -}); +const instance = new Temporal.PlainYearMonth(2019, 10); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ year: 2020 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js index 587c66754c8..4684d597f3e 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/with/overflow-invalid-string.js @@ -17,6 +17,12 @@ features: [Temporal] ---*/ const yearmonth = new Temporal.PlainYearMonth(2000, 5); -for (const overflow of ["", "CONSTRAIN", "balance", "other string", "constra\u0131n"]) { - assert.throws(RangeError, () => yearmonth.with({ month: 8 }, { overflow })); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => yearmonth.with({ month: 8 }, { overflow }), + `invalid overflow ("${overflow}")` + ); } diff --git a/test/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js b/test/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.js new file mode 100644 index 00000000000..eaa0b1239d0 --- /dev/null +++ b/test/built-ins/Temporal/TimeZone/prototype/getInstantFor/options-wrong-type.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.timezone.prototype.getinstantfor +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.TimeZone("UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.getInstantFor(new Temporal.PlainDateTime(2019, 10, 29, 10, 46, 38), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/from/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/from/options-wrong-type.js new file mode 100644 index 00000000000..91fb3bab63e --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/from/options-wrong-type.js @@ -0,0 +1,22 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +for (const value of badOptions) { + assert.throws(TypeError, () => Temporal.ZonedDateTime.from({ year: 1976, month: 11, day: 18, timeZone: "UTC" }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js index 5913d3e7f96..e8406c57e37 100644 --- a/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/from/overflow-invalid-string.js @@ -32,6 +32,14 @@ const validValues = [ { year: 2000, month: 5, day: 2, hour: 12, timeZone: "UTC" }, "2001-09-09T01:46:40.987654321+00:00[UTC]", ]; -validValues.forEach((value) => { - assert.throws(RangeError, () => Temporal.ZonedDateTime.from(value, { overflow: "other string" })); -}); + +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const value of validValues) { + for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => Temporal.ZonedDateTime.from(value, { overflow }), + `invalid overflow ("${overflow}")` + ); + } +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/add/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/add/options-wrong-type.js new file mode 100644 index 00000000000..b107f23ee02 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/add/options-wrong-type.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.zoneddatetime.prototype.add +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.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.add({ years: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js index 4c88b568784..ede72ad4a96 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/add/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); const duration = new Temporal.Duration(0, 0, 0, 1); -assert.throws(RangeError, () => datetime.add(duration, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.add(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/round/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/round/options-wrong-type.js new file mode 100644 index 00000000000..e54dcd45e6c --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/round/options-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-temporal.zoneddatetime.prototype.round +description: TypeError thrown when options argument is missing or a non-string primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + undefined, + null, + true, + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); +assert.throws(TypeError, () => instance.round(), "TypeError on missing options argument"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.round(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/round/rounding-direction.js b/test/built-ins/Temporal/ZonedDateTime/prototype/round/rounding-direction.js new file mode 100644 index 00000000000..676841ed26d --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/round/rounding-direction.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(-65_261_246_399_500_000_000n, "UTC"); // -000099-12-15T12:00:00.5Z +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "floor" }).epochNanoseconds, + -65_261_246_400_000_000_000n, // -000099-12-15T12:00:00Z + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode floor)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "trunc" }).epochNanoseconds, + -65_261_246_400_000_000_000n, // -000099-12-15T12:00:00Z + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "ceil" }).epochNanoseconds, + -65_261_246_399_000_000_000n, // -000099-12-15T12:00:01Z + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +assert.sameValue( + instance.round({ smallestUnit: "second", roundingMode: "halfExpand" }).epochNanoseconds, + -65_261_246_399_000_000_000n, // -000099-12-15T12:00:01Z + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js index bee6892ba97..cf8831a9756 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/round/smallestunit-invalid-string.js @@ -8,4 +8,26 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); -assert.throws(RangeError, () => datetime.round({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => datetime.round({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 00000000000..9e6556718c8 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,68 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const earlier = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Basic difference with largestUnit larger than days. +// The calls come from these paths: +// ZonedDateTime.since() -> DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const later1 = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calendar); +later1.since(earlier, { largestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit >days"); + +// Basic difference with largestUnit equal to days, to cover the second path in +// AddZonedDateTime. +// The calls come from these paths: +// ZonedDateTime.since() -> DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +later1.since(earlier, { largestUnit: "days" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit days"); + +// Difference with rounding, with smallestUnit a calendar unit. +// The calls come from these paths: +// ZonedDateTime.since() -> +// DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +later1.since(earlier, { smallestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with calendar smallestUnit"); + +// Difference with rounding, with smallestUnit a non-calendar unit, and having +// the resulting time difference be longer than a calendar day, covering the +// paths that go through AdjustRoundedDurationDays. (The path through +// AdjustRoundedDurationDays -> AddDuration that's covered in the corresponding +// test in until() only happens in one direction.) +// The calls come from these paths: +// ZonedDateTime.since() -> +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (3x) +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (3x) + +calendar.dateAddCallCount = 0; + +const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar); +later2.since(earlier, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" }); +assert.sameValue(calendar.dateAddCallCount, 6, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js index 61dd7f3ad39..9e96e8a4965 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/largestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); -const values = ["era", "eraYear", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/options-wrong-type.js new file mode 100644 index 00000000000..f2f30920733 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/options-wrong-type.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.zoneddatetime.prototype.since +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.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.since(new Temporal.ZonedDateTime(3600_000_000_000n, "UTC"), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js index 5735fba65e7..a116e240745 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/smallestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); -const values = ["era", "eraYear", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => later.since(earlier, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-wrong-type.js new file mode 100644 index 00000000000..d06125ab40a --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/options-wrong-type.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.zoneddatetime.prototype.subtract +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.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.subtract({ years: 1 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js index 8c144ef70d0..7a7d4fd1206 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/subtract/overflow-invalid-string.js @@ -20,4 +20,11 @@ features: [Temporal] const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); const duration = new Temporal.Duration(0, 0, 0, 1); -assert.throws(RangeError, () => datetime.subtract(duration, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.subtract(duration, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js new file mode 100644 index 00000000000..d532f99c4a6 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toJSON/year-format.js @@ -0,0 +1,55 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tojson +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +const utc = new Temporal.TimeZone("UTC"); + +let instance = new Temporal.ZonedDateTime(epochNsInYear(-100000n), utc); +assert.sameValue(instance.toJSON(), "-100000-07-01T21:30:36+00:00[UTC]", "large negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-10000n), utc); +assert.sameValue(instance.toJSON(), "-010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-9999n), utc); +assert.sameValue(instance.toJSON(), "-009999-07-02T03:19:48+00:00[UTC]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1000n), utc); +assert.sameValue(instance.toJSON(), "-001000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-999n), utc); +assert.sameValue(instance.toJSON(), "-000999-07-02T15:19:48+00:00[UTC]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1n), utc); +assert.sameValue(instance.toJSON(), "-000001-07-02T15:41:24+00:00[UTC]", "year -1 formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(0n), utc); +assert.sameValue(instance.toJSON(), "0000-07-01T21:30:36+00:00[UTC]", "year 0 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1n), utc); +assert.sameValue(instance.toJSON(), "0001-07-02T03:19:48+00:00[UTC]", "year 1 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(999n), utc); +assert.sameValue(instance.toJSON(), "0999-07-02T03:41:24+00:00[UTC]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1000n), utc); +assert.sameValue(instance.toJSON(), "1000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(9999n), utc); +assert.sameValue(instance.toJSON(), "9999-07-02T15:41:24+00:00[UTC]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(10000n), utc); +assert.sameValue(instance.toJSON(), "+010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(100000n), utc); +assert.sameValue(instance.toJSON(), "+100000-07-01T21:30:36+00:00[UTC]", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..e1925185c5d --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainMonthDay/calendar-monthdayfromfields-called-with-options-undefined.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.zoneddatetime.prototype.toplainmonthday +description: > + Calendar.monthDayFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.toPlainMonthDay(); +assert.sameValue(calendar.monthDayFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..8f75ba30b57 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toPlainYearMonth/calendar-yearmonthfromfields-called-with-options-undefined.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.zoneddatetime.prototype.toplainyearmonth +description: > + Calendar.yearMonthFromFields method is called with undefined as the options + value when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.toPlainYearMonth(); +assert.sameValue(calendar.yearMonthFromFieldsCallCount, 1); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-auto.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 00000000000..bffb9289511 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-auto.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.zoneddatetime.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [BigInt, Temporal] +---*/ + +const zeroSeconds = new Temporal.ZonedDateTime(0n, "UTC"); +const wholeSeconds = new Temporal.ZonedDateTime(30_000_000_000n, "UTC"); +const subSeconds = new Temporal.ZonedDateTime(30_123_400_000n, "UTC"); + +const tests = [ + [zeroSeconds, "1970-01-01T00:00:00+00:00[UTC]"], + [wholeSeconds, "1970-01-01T00:00:30+00:00[UTC]"], + [subSeconds, "1970-01-01T00:00:30.1234+00:00[UTC]"], +]; + +for (const [datetime, expected] of tests) { + assert.sameValue(datetime.toString(), expected, "default is to emit seconds and drop trailing zeroes"); + assert.sameValue(datetime.toString({ fractionalSecondDigits: "auto" }), expected, "auto is the default"); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js index ea172ceb80e..c933354b9d4 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -9,11 +9,14 @@ info: | 4. If _stringValues_ is not *undefined* and _stringValues_ does not contain an element equal to _value_, throw a *RangeError* exception. sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). - sec-temporal.instant.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + sec-temporal.zoneddatetime.prototype.tostring step 4: + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: "other string" })); +for (const fractionalSecondDigits of ["other string", "AUTO", "not-auto", "autos", "auto\0"]) { + assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js index 93685aedece..a9ccce61d8d 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -10,7 +10,7 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.zoneddatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-number.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 00000000000..0063031f203 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-number.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.zoneddatetime.prototype.tostring +description: Number for fractionalSecondDigits option +features: [BigInt, Temporal] +---*/ + +const zeroSeconds = new Temporal.ZonedDateTime(0n, "UTC"); +const wholeSeconds = new Temporal.ZonedDateTime(30_000_000_000n, "UTC"); +const subSeconds = new Temporal.ZonedDateTime(30_123_400_000n, "UTC"); + +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 0 }), "1970-01-01T00:00:30+00:00[UTC]", + "truncates 4 decimal places to 0"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:00.00+00:00[UTC]", + "pads zero seconds to 2 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:30.00+00:00[UTC]", + "pads whole seconds to 2 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 2 }), "1970-01-01T00:00:30.12+00:00[UTC]", + "truncates 4 decimal places to 2"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 3 }), "1970-01-01T00:00:30.123+00:00[UTC]", + "truncates 4 decimal places to 3"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 6 }), "1970-01-01T00:00:30.123400+00:00[UTC]", + "pads 4 decimal places to 6"); +assert.sameValue(zeroSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:00.0000000+00:00[UTC]", + "pads zero seconds to 7 decimal places"); +assert.sameValue(wholeSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:30.0000000+00:00[UTC]", + "pads whole seconds to 7 decimal places"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 7 }), "1970-01-01T00:00:30.1234000+00:00[UTC]", + "pads 4 decimal places to 7"); +assert.sameValue(subSeconds.toString({ fractionalSecondDigits: 9 }), "1970-01-01T00:00:30.123400000+00:00[UTC]", + "pads 4 decimal places to 9"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js index 36ae8d14293..487600a4158 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -10,11 +10,17 @@ info: | sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.zoneddatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 })); -assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 })); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -Infinity }), + "−∞ is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: -1 }), + "−1 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 10 }), + "10 is out of range for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: Infinity }), + "∞ is out of range for fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js index a4e0a10b5f0..734f436c4c3 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-undefined.js @@ -8,17 +8,31 @@ info: | sec-getoption step 3: 3. If _value_ is *undefined*, return _fallback_. sec-getstringornumberoption step 2: - 2. Let _value_ be ? GetOption(_options_, _property_, *"stringOrNumber"*, *undefined*, _fallback_). + 2. Let _value_ be ? GetOption(_options_, _property_, « Number, String », *undefined*, _fallback_). sec-temporal-tosecondsstringprecision step 9: 9. Let _digits_ be ? GetStringOrNumberOption(_normalizedOptions_, *"fractionalSecondDigits"*, « *"auto"* », 0, 9, *"auto"*). sec-temporal.zoneddatetime.prototype.tostring step 4: - 4. Let _precision_ be ? ToDurationSecondsStringPrecision(_options_). + 4. Let _precision_ be ? ToSecondsStringPrecision(_options_). features: [Temporal] ---*/ -const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); +const zeroSeconds = new Temporal.ZonedDateTime(0n, "UTC"); +const wholeSeconds = new Temporal.ZonedDateTime(30_000_000_000n, "UTC"); +const subSeconds = new Temporal.ZonedDateTime(30_123_400_000n, "UTC"); -const explicit = datetime.toString({ fractionalSecondDigits: undefined }); -assert.sameValue(explicit, "2001-09-09T01:46:40.98765+00:00[UTC]", "default fractionalSecondDigits is auto"); +const tests = [ + [zeroSeconds, "1970-01-01T00:00:00+00:00[UTC]"], + [wholeSeconds, "1970-01-01T00:00:30+00:00[UTC]"], + [subSeconds, "1970-01-01T00:00:30.1234+00:00[UTC]"], +]; -// See options-undefined.js for {} +for (const [datetime, expected] of tests) { + const explicit = datetime.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); + + const implicit = datetime.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); + + const lambda = datetime.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js index b147dbac3e2..9a12691ad6d 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -22,4 +22,26 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_650_000n, "UTC"); -TemporalHelpers.checkFractionalSecondDigitsOptionWrongType(datetime); + +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: null }), + "null is not a number and converts to the string 'null' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: true }), + "true is not a number and converts to the string 'true' which is not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: false }), + "false is not a number and converts to the string 'false' which is not valid for fractionalSecondDigits"); +assert.throws(TypeError, () => datetime.toString({ fractionalSecondDigits: Symbol() }), + "symbols are not numbers and cannot convert to strings"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: 2n }), + "bigints are not numbers and convert to strings which are not valid for fractionalSecondDigits"); +assert.throws(RangeError, () => datetime.toString({ fractionalSecondDigits: {} }), + "plain objects are not numbers and convert to strings which are not valid for fractionalSecondDigits"); + +const expected = [ + "get fractionalSecondDigits.toString", + "call fractionalSecondDigits.toString", +]; +const actual = []; +const observer = TemporalHelpers.toPrimitiveObserver(actual, "auto", "fractionalSecondDigits"); +const result = datetime.toString({ fractionalSecondDigits: observer }); +assert.sameValue(result, "2001-09-09T01:46:40.98765+00:00[UTC]", "object with toString uses toString return value"); +assert.compareArray(actual, expected, "object with toString calls toString and not valueOf"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/options-wrong-type.js new file mode 100644 index 00000000000..4b579b44d01 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/options-wrong-type.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.zoneddatetime.prototype.tostring +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.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.toString(value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-cross-midnight.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-cross-midnight.js new file mode 100644 index 00000000000..a55db0f240e --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-cross-midnight.js @@ -0,0 +1,13 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Rounding can cross midnight +features: [Temporal] +---*/ + +const zonedDateTime = new Temporal.ZonedDateTime(946_684_799_999_999_999n, "UTC"); // one nanosecond before 2000-01-01T00:00:00 +for (const roundingMode of ["ceil", "halfExpand"]) { + assert.sameValue(zonedDateTime.toString({ fractionalSecondDigits: 8, roundingMode }), "2000-01-01T00:00:00.00000000+00:00[UTC]"); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-direction.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-direction.js new file mode 100644 index 00000000000..b376e075bb8 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/rounding-direction.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Rounding down is towards the Big Bang, not the epoch or 1 BCE +features: [Temporal] +---*/ + +const instance = new Temporal.ZonedDateTime(-65_261_246_399_500_000_000n, "UTC"); // -000099-12-15T12:00:00.5Z +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "floor" }), + "-000099-12-15T12:00:00+00:00[UTC]", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "trunc" }), + "-000099-12-15T12:00:00+00:00[UTC]", + "Rounding down is towards the Big Bang, not the epoch or 1 BCE (roundingMode trunc)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "ceil" }), + "-000099-12-15T12:00:01+00:00[UTC]", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode ceil)" +); +assert.sameValue( + instance.toString({ smallestUnit: "second", roundingMode: "halfExpand" }), + "-000099-12-15T12:00:01+00:00[UTC]", + "Rounding up is away from the Big Bang, not the epoch or 1 BCE (roundingMode halfExpand)" +); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-ceil.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-ceil.js new file mode 100644 index 00000000000..cd9c1af1edc --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-ceil.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.zoneddatetime.prototype.tostring +description: ceil value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "ceil" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123988+00:00[UTC]", + "roundingMode is ceil (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "ceil" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123988+00:00[UTC]", + "roundingMode is ceil (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "ceil" }); +assert.sameValue(result3, "2001-09-09T01:46:40.124+00:00[UTC]", + "roundingMode is ceil (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "ceil" }); +assert.sameValue(result4, "2001-09-09T01:46:40.124+00:00[UTC]", + "roundingMode is ceil (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "ceil" }); +assert.sameValue(result5, "2001-09-09T01:46:41+00:00[UTC]", + "roundingMode is ceil (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "ceil" }); +assert.sameValue(result6, "2001-09-09T01:46:41+00:00[UTC]", + "roundingMode is ceil (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "ceil" }); +assert.sameValue(result7, "2001-09-09T01:47+00:00[UTC]", "roundingMode is ceil (round to minute)"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-floor.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-floor.js new file mode 100644 index 00000000000..fec4286c461 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-floor.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.zoneddatetime.prototype.tostring +description: floor value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "floor" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123987+00:00[UTC]", + "roundingMode is floor (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "floor" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123987+00:00[UTC]", + "roundingMode is floor (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "floor" }); +assert.sameValue(result3, "2001-09-09T01:46:40.123+00:00[UTC]", + "roundingMode is floor (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "floor" }); +assert.sameValue(result4, "2001-09-09T01:46:40.123+00:00[UTC]", + "roundingMode is floor (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "floor" }); +assert.sameValue(result5, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is floor (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "floor" }); +assert.sameValue(result6, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is floor (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "floor" }); +assert.sameValue(result7, "2001-09-09T01:46+00:00[UTC]", "roundingMode is floor (round to minute)"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-halfExpand.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 00000000000..a4a989cb6ed --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-halfExpand.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.zoneddatetime.prototype.tostring +description: halfExpand value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "halfExpand" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123988+00:00[UTC]", + "roundingMode is halfExpand (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "halfExpand" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123988+00:00[UTC]", + "roundingMode is halfExpand (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "halfExpand" }); +assert.sameValue(result3, "2001-09-09T01:46:40.124+00:00[UTC]", + "roundingMode is halfExpand (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "halfExpand" }); +assert.sameValue(result4, "2001-09-09T01:46:40.124+00:00[UTC]", + "roundingMode is halfExpand (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "halfExpand" }); +assert.sameValue(result5, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is halfExpand (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "halfExpand" }); +assert.sameValue(result6, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is halfExpand (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "halfExpand" }); +assert.sameValue(result7, "2001-09-09T01:47+00:00[UTC]", "roundingMode is halfExpand (round to minute)"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-trunc.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-trunc.js new file mode 100644 index 00000000000..8fc3ca0dca9 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/roundingmode-trunc.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.zoneddatetime.prototype.tostring +description: trunc value for roundingMode option +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); + +const result1 = datetime.toString({ smallestUnit: "microsecond", roundingMode: "trunc" }); +assert.sameValue(result1, "2001-09-09T01:46:40.123987+00:00[UTC]", + "roundingMode is trunc (with 6 digits from smallestUnit)"); + +const result2 = datetime.toString({ fractionalSecondDigits: 6, roundingMode: "trunc" }); +assert.sameValue(result2, "2001-09-09T01:46:40.123987+00:00[UTC]", + "roundingMode is trunc (with 6 digits from fractionalSecondDigits)"); + +const result3 = datetime.toString({ smallestUnit: "millisecond", roundingMode: "trunc" }); +assert.sameValue(result3, "2001-09-09T01:46:40.123+00:00[UTC]", + "roundingMode is trunc (with 3 digits from smallestUnit)"); + +const result4 = datetime.toString({ fractionalSecondDigits: 3, roundingMode: "trunc" }); +assert.sameValue(result4, "2001-09-09T01:46:40.123+00:00[UTC]", + "roundingMode is trunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = datetime.toString({ smallestUnit: "second", roundingMode: "trunc" }); +assert.sameValue(result5, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is trunc (with 0 digits from smallestUnit)"); + +const result6 = datetime.toString({ fractionalSecondDigits: 0, roundingMode: "trunc" }); +assert.sameValue(result6, "2001-09-09T01:46:40+00:00[UTC]", + "roundingMode is trunc (with 0 digits from fractionalSecondDigits)"); + +const result7 = datetime.toString({ smallestUnit: "minute", roundingMode: "trunc" }); +assert.sameValue(result7, "2001-09-09T01:46+00:00[UTC]", "roundingMode is trunc (round to minute)"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-fractionalseconddigits.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 00000000000..7845c10bfb2 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-fractionalseconddigits.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(56_789_999_999n, "UTC"); +const tests = [ + ["minute", "1970-01-01T00:00+00:00[UTC]"], + ["second", "1970-01-01T00:00:56+00:00[UTC]"], + ["millisecond", "1970-01-01T00:00:56.789+00:00[UTC]"], + ["microsecond", "1970-01-01T00:00:56.789999+00:00[UTC]"], + ["nanosecond", "1970-01-01T00:00:56.789999999+00:00[UTC]"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = datetime.toString({ + smallestUnit, + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } + }); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); +} + +assert.throws(RangeError, () => datetime.toString({ + smallestUnit: "hour", + get fractionalSecondDigits() { throw new Test262Error("should not get fractionalSecondDigits") } +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js index d3940464811..1ba9732789b 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-invalid-string.js @@ -8,4 +8,30 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_987_500n, "UTC"); -assert.throws(RangeError, () => datetime.toString({ smallestUnit: "other string" })); +const badValues = [ + "era", + "eraYear", + "year", + "month", + "week", + "day", + "hour", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "years", + "months", + "weeks", + "days", + "hours", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js index 12c10368b64..6ea787955a9 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/smallestunit-valid-units.js @@ -9,13 +9,39 @@ features: [Temporal] const datetime = new Temporal.ZonedDateTime(1_000_000_000_123_456_789n, "UTC"); -assert.sameValue(datetime.toString({ smallestUnit: "minute" }), "2001-09-09T01:46+00:00[UTC]"); -assert.sameValue(datetime.toString({ smallestUnit: "second" }), "2001-09-09T01:46:40+00:00[UTC]"); -assert.sameValue(datetime.toString({ smallestUnit: "millisecond" }), "2001-09-09T01:46:40.123+00:00[UTC]"); -assert.sameValue(datetime.toString({ smallestUnit: "microsecond" }), "2001-09-09T01:46:40.123456+00:00[UTC]"); -assert.sameValue(datetime.toString({ smallestUnit: "nanosecond" }), "2001-09-09T01:46:40.123456789+00:00[UTC]"); +function test(instance, expectations, description) { + for (const [smallestUnit, expectedResult] of expectations) { + assert.sameValue(instance.toString({ smallestUnit }), expectedResult, + `${description} with smallestUnit "${smallestUnit}"`); + } +} + +test( + datetime, + [ + ["minute", "2001-09-09T01:46+00:00[UTC]"], + ["second", "2001-09-09T01:46:40+00:00[UTC]"], + ["millisecond", "2001-09-09T01:46:40.123+00:00[UTC]"], + ["microsecond", "2001-09-09T01:46:40.123456+00:00[UTC]"], + ["nanosecond", "2001-09-09T01:46:40.123456789+00:00[UTC]"], + ], + "subseconds toString" +); + +test( + new Temporal.ZonedDateTime(999_999_960_000_000_000n, "UTC"), + [ + ["minute", "2001-09-09T01:46+00:00[UTC]"], + ["second", "2001-09-09T01:46:00+00:00[UTC]"], + ["millisecond", "2001-09-09T01:46:00.000+00:00[UTC]"], + ["microsecond", "2001-09-09T01:46:00.000000+00:00[UTC]"], + ["nanosecond", "2001-09-09T01:46:00.000000000+00:00[UTC]"], + ], + "whole minutes toString" +); const notValid = [ + "era", "year", "month", "week", @@ -24,5 +50,6 @@ const notValid = [ ]; notValid.forEach((smallestUnit) => { - assert.throws(RangeError, () => datetime.toString({ smallestUnit }), smallestUnit); + assert.throws(RangeError, () => datetime.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); }); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js new file mode 100644 index 00000000000..1532bf1fecd --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/toString/year-format.js @@ -0,0 +1,55 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.tostring +description: Verify that the year is appropriately formatted as 4 or 6 digits +features: [Temporal] +---*/ + +function epochNsInYear(year) { + // Return an epoch nanoseconds value near the middle of the given year + const avgNsPerYear = 31_556_952_000_000_000n; + return (year - 1970n) * avgNsPerYear + (avgNsPerYear / 2n); +} + +const utc = new Temporal.TimeZone("UTC"); + +let instance = new Temporal.ZonedDateTime(epochNsInYear(-100000n), utc); +assert.sameValue(instance.toString(), "-100000-07-01T21:30:36+00:00[UTC]", "large negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-10000n), utc); +assert.sameValue(instance.toString(), "-010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-9999n), utc); +assert.sameValue(instance.toString(), "-009999-07-02T03:19:48+00:00[UTC]", "largest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1000n), utc); +assert.sameValue(instance.toString(), "-001000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-999n), utc); +assert.sameValue(instance.toString(), "-000999-07-02T15:19:48+00:00[UTC]", "largest 3-digit negative year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(-1n), utc); +assert.sameValue(instance.toString(), "-000001-07-02T15:41:24+00:00[UTC]", "year -1 formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(0n), utc); +assert.sameValue(instance.toString(), "0000-07-01T21:30:36+00:00[UTC]", "year 0 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1n), utc); +assert.sameValue(instance.toString(), "0001-07-02T03:19:48+00:00[UTC]", "year 1 formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(999n), utc); +assert.sameValue(instance.toString(), "0999-07-02T03:41:24+00:00[UTC]", "largest 3-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(1000n), utc); +assert.sameValue(instance.toString(), "1000-07-02T09:30:36+00:00[UTC]", "smallest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(9999n), utc); +assert.sameValue(instance.toString(), "9999-07-02T15:41:24+00:00[UTC]", "largest 4-digit positive year formatted as 4-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(10000n), utc); +assert.sameValue(instance.toString(), "+010000-07-01T21:30:36+00:00[UTC]", "smallest 5-digit positive year formatted as 6-digit"); + +instance = new Temporal.ZonedDateTime(epochNsInYear(100000n), utc); +assert.sameValue(instance.toString(), "+100000-07-01T21:30:36+00:00[UTC]", "large positive year formatted as 6-digit"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js new file mode 100644 index 00000000000..13bdd33972e --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js @@ -0,0 +1,69 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +description: > + BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the + options value +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarDateAddUndefinedOptions(); +const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9); +const earlier = new Temporal.ZonedDateTime(0n, timeZone, calendar); + +// Basic difference with largestUnit larger than days. +// The calls come from these paths: +// ZonedDateTime.until() -> DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() + +const later1 = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calendar); +earlier.until(later1, { largestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit >days"); + +// Basic difference with largestUnit equal to days, to cover the second path in +// AddZonedDateTime. +// The calls come from these paths: +// ZonedDateTime.until() -> DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +earlier.until(later1, { largestUnit: "days" }); +assert.sameValue(calendar.dateAddCallCount, 2, "basic difference with largestUnit days"); + +// Difference with rounding, with smallestUnit a calendar unit. +// The calls come from these paths: +// ZonedDateTime.until() -> +// DifferenceZonedDateTime -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// RoundDuration -> +// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// MoveRelativeDate -> calendar.dateAdd() + +calendar.dateAddCallCount = 0; + +earlier.until(later1, { smallestUnit: "weeks" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with calendar smallestUnit"); + +// Difference with rounding, with smallestUnit a non-calendar unit, and having +// the resulting time difference be longer than a calendar day, covering the +// paths that go through AdjustRoundedDurationDays. +// The calls come from these paths: +// ZonedDateTime.until() -> +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AdjustRoundedDurationDays -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// AddDuration -> +// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() +// DifferenceZonedDateTime -> NanosecondsToDays -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x) + +calendar.dateAddCallCount = 0; + +const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar); +earlier.until(later2, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" }); +assert.sameValue(calendar.dateAddCallCount, 5, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js index a59c2f2e43c..2be916f1778 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/largestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); -const values = ["era", "eraYear", "other string"]; -for (const largestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { largestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string" +]; +for (const largestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { largestUnit }), + `"${largestUnit}" is not a valid value for largestUnit`); } diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/options-wrong-type.js new file mode 100644 index 00000000000..55b128637ea --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/options-wrong-type.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.zoneddatetime.prototype.until +description: TypeError thrown when options argument is a primitive +features: [BigInt, Symbol, Temporal] +---*/ + +const badOptions = [ + null, + true, + "some string", + Symbol(), + 1, + 2n, +]; + +const instance = new Temporal.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.until(new Temporal.ZonedDateTime(3600_000_000_000n, "UTC"), value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js index 42f55bc8503..4f09f10f688 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/smallestunit-invalid-string.js @@ -9,7 +9,20 @@ features: [Temporal] const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_090_061_987_654_321n, "UTC"); -const values = ["era", "eraYear", "other string"]; -for (const smallestUnit of values) { - assert.throws(RangeError, () => earlier.until(later, { smallestUnit })); +const badValues = [ + "era", + "eraYear", + "millisecond\0", + "mill\u0131second", + "SECOND", + "eras", + "eraYears", + "milliseconds\0", + "mill\u0131seconds", + "SECONDS", + "other string", +]; +for (const smallestUnit of badValues) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit }), + `"${smallestUnit}" is not a valid value for smallest unit`); } diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js b/test/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.js new file mode 100644 index 00000000000..5f4d25d9305 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/with/options-wrong-type.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.zoneddatetime.prototype.with +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.ZonedDateTime(0n, "UTC"); +for (const value of badOptions) { + assert.throws(TypeError, () => instance.with({ day: 5 }, value), + `TypeError on wrong options type ${typeof value}`); +}; diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js b/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js index 96d5ab3799d..843437f59fd 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/with/overflow-invalid-string.js @@ -18,4 +18,11 @@ features: [Temporal] ---*/ const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC"); -assert.throws(RangeError, () => datetime.with({ minute: 45 }, { overflow: "other string" })); +const badOverflows = ["", "CONSTRAIN", "balance", "other string", "constra\u0131n", "reject\0"]; +for (const overflow of badOverflows) { + assert.throws( + RangeError, + () => datetime.with({ minute: 45 }, { overflow }), + `invalid overflow ("${overflow}")` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js new file mode 100644 index 00000000000..003bf13f1b8 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.withplaindate +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.withPlainDate(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..f19cc9fac12 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/withPlainDate/calendar-datefromfields-called-with-options-undefined.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.zoneddatetime.prototype.withplaindate +description: > + Calendar.dateFromFields method is called with undefined as the options value + when call originates internally +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarFromFieldsUndefinedOptions(); +const instance = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC", calendar); +instance.withPlainDate({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/built-ins/TypedArray/prototype/set/BigInt/array-arg-targetbuffer-detached-on-get-src-value-throws.js b/test/built-ins/TypedArray/prototype/set/BigInt/array-arg-targetbuffer-detached-on-get-src-value-throws.js deleted file mode 100644 index 568e8b9b08a..00000000000 --- a/test/built-ins/TypedArray/prototype/set/BigInt/array-arg-targetbuffer-detached-on-get-src-value-throws.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.set-array-offset -description: > - Throws an error if buffer is detached before setting a value -info: | - 22.2.3.23.1 %TypedArray%.prototype.set (array [ , offset ] ) - - 1. Assert: array is any ECMAScript language value other than an Object with a - [[TypedArrayName]] internal slot. If it is such an Object, the definition in - 22.2.3.23.2 applies. - ... - 21. Repeat, while targetByteIndex < limit - a. Let Pk be ! ToString(k). - b. Let kNumber be ? ToNumber(? Get(src, Pk)). - c. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. - d. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, - kNumber). - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA([1n, 2n, 3n]); - var obj = { - length: 3, - "0": 42n - }; - Object.defineProperty(obj, 1, { - get: function() { - $DETACHBUFFER(sample.buffer); - } - }); - Object.defineProperty(obj, 2, { - get: function() { - throw new Test262Error("Should not get other values"); - } - }); - - assert.throws(TypeError, function() { - sample.set(obj); - }); -}); diff --git a/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js b/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js new file mode 100644 index 00000000000..1d514622089 --- /dev/null +++ b/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-no-throw.js @@ -0,0 +1,36 @@ +// Copyright (C) 2022 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-%typedarray%.prototype.set-array-offset +description: > + Does not throw if target TA is detached mid-iteration +includes: [testTypedArray.js, detachArrayBuffer.js] +features: [TypedArray] +---*/ + +testWithTypedArrayConstructors(function(TA) { + var sample = new TA([1, 2, 3]); + var obj = { + length: 3, + "0": 42 + }; + Object.defineProperty(obj, 1, { + get: function() { + $DETACHBUFFER(sample.buffer); + } + }); + let get2Called = false; + Object.defineProperty(obj, 2, { + get: function() { + get2Called = true; + return 2; + } + }); + + sample.set(obj); + + assert.sameValue(true, get2Called); + assert.sameValue(0, sample.byteLength); + assert.sameValue(0, sample.byteOffset); + assert.sameValue(0, sample.length); +}); diff --git a/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js b/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js deleted file mode 100644 index eed7db0831a..00000000000 --- a/test/built-ins/TypedArray/prototype/set/array-arg-targetbuffer-detached-on-get-src-value-throws.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.set-array-offset -description: > - Throws an error if buffer is detached before setting a value -info: | - 22.2.3.23.1 %TypedArray%.prototype.set (array [ , offset ] ) - - 1. Assert: array is any ECMAScript language value other than an Object with a - [[TypedArrayName]] internal slot. If it is such an Object, the definition in - 22.2.3.23.2 applies. - ... - 21. Repeat, while targetByteIndex < limit - a. Let Pk be ! ToString(k). - b. Let kNumber be ? ToNumber(? Get(src, Pk)). - c. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError exception. - d. Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, - kNumber). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA([1, 2, 3]); - var obj = { - length: 3, - "0": 42 - }; - Object.defineProperty(obj, 1, { - get: function() { - $DETACHBUFFER(sample.buffer); - } - }); - Object.defineProperty(obj, 2, { - get: function() { - throw new Test262Error("Should not get other values"); - } - }); - - assert.throws(TypeError, function() { - sample.set(obj); - }); -}); diff --git a/test/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js b/test/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js deleted file mode 100644 index caa7f80a28a..00000000000 --- a/test/built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: Throws a TypeError if comparefn detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? Call(comparefn, undefined, « x, y »). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - $DETACHBUFFER(sample.buffer); - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }); - - assert.sameValue(calls, 1); -}); diff --git a/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js b/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js deleted file mode 100644 index 6e2be4cafda..00000000000 --- a/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn-coerce.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2020 Google. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: > - SECURITY Throws a TypeError if coercion of the comparefn return value - detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? ToNumber(? Call(comparefn, undefined, « x, y »)). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var convertfn = function(){ - $DETACHBUFFER(sample.buffer); - return 1; - } - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - return {valueOf : convertfn} - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }, "Coercion that detaches buffer should throw TypeError"); - - assert.sameValue(calls, 1); -}); diff --git a/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js b/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js deleted file mode 100644 index 6ff08beb603..00000000000 --- a/test/built-ins/TypedArray/prototype/sort/detached-buffer-comparefn.js +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-%typedarray%.prototype.sort -description: Throws a TypeError if comparefn detaches the object buffer -info: | - 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) - - When the TypedArray SortCompare abstract operation is called with two - arguments x and y, the following steps are taken: - - ... - 2. If the argument comparefn is not undefined, then - a. Let v be ? Call(comparefn, undefined, « x, y »). - b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. - ... - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(4); - var calls = 0; - var comparefn = function() { - if (calls > 0) { - throw new Test262Error(); - } - calls++; - $DETACHBUFFER(sample.buffer); - }; - - assert.throws(TypeError, function() { - sample.sort(comparefn); - }); - - assert.sameValue(calls, 1); -}); diff --git a/test/built-ins/TypedArray/prototype/sort/sort-tonumber.js b/test/built-ins/TypedArray/prototype/sort/sort-tonumber.js index 627ed55ecdf..36d8457e980 100644 --- a/test/built-ins/TypedArray/prototype/sort/sort-tonumber.js +++ b/test/built-ins/TypedArray/prototype/sort/sort-tonumber.js @@ -21,16 +21,12 @@ testWithTypedArrayConstructors(function(TA) { var ab = ta.buffer; var called = false; - assert.throws(TypeError, function() { - ta.sort(function(a, b) { - // IsDetachedBuffer is checked right after calling comparefn. - // So, detach the ArrayBuffer to cause sort to throw, to make sure we're actually calling ToNumber immediately (as spec'd) - // (a possible bug is to wait until the result is inspected to call ToNumber, rather than immediately) - $DETACHBUFFER(ab); - return { - [Symbol.toPrimitive]() { called = true; } - }; - }); + ta.sort(function(a, b) { + // Detaching the buffer does not cause sort to throw. + $DETACHBUFFER(ab); + return { + [Symbol.toPrimitive]() { called = true; } + }; }); assert.sameValue(true, called); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js deleted file mode 100644 index 4b914e6d2ef..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-different-type.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with a different element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - ... - 19. Else, - a. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - b. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray, Symbol.species] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - var targetType = TA !== BigInt64Array ? BigInt64Array : BigUint64Array; - new targetType(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js deleted file mode 100644 index c4f45c49c7c..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/detached-when-species-retrieved-same-type.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with the same element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ) - - ... - 3. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength). - 4. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testBigIntTypedArray.js, detachArrayBuffer.js] -features: [BigInt, TypedArray, Symbol.species] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - new TA(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index 3882f1c78e8..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var OtherCtor = TA === BigInt64Array ? BigUint64Array : BigInt64Array; - var sample = new OtherCtor(); - - Object.defineProperty(sample.buffer, "constructor", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js deleted file mode 100644 index 5a5d7ee0ab7..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, cross-realm, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js deleted file mode 100644 index 1ff1e5db533..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-custom-species.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js deleted file mode 100644 index 44b76c2b95e..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ""; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol("1"); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js deleted file mode 100644 index 8b3933eedb5..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js deleted file mode 100644 index 09a8068e9f2..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -var ctor = function() { - throw new Test262Error(); -}; -var m = { m() {} }.m; -ctor[Symbol.species] = m; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - - sample.buffer.constructor = ctor; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 705b8a7319c..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -var sample1 = new BigInt64Array(); -var sample2 = new BigUint64Array(); - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = TA === BigInt64Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() {called++;}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index 51fa9a8358f..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - Object.defineProperty(sample.buffer, "constructor", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js deleted file mode 100644 index 90de9642805..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, cross-realm, Symbol.species, TypedArray] ----*/ - -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js deleted file mode 100644 index 743b03e3f4b..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-custom.js +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js deleted file mode 100644 index 32cbc01bc3f..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var m = { m() {} }; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = m; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 042d4213db8..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function(){}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js deleted file mode 100644 index 0aa7517b802..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-species-throws.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol.species, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js b/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js deleted file mode 100644 index a3ca9a041b3..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors-bigint/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testBigIntTypedArray.js] -features: [BigInt, Symbol, TypedArray] ----*/ - -testWithBigIntTypedArrayConstructors(function(TA) { - var sample = new TA(); - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ''; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol('1'); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/no-species.js b/test/built-ins/TypedArrayConstructors/ctors/no-species.js new file mode 100644 index 00000000000..9fdced7e986 --- /dev/null +++ b/test/built-ins/TypedArrayConstructors/ctors/no-species.js @@ -0,0 +1,30 @@ +// Copyright (C) 2022 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Creating TypedArray from other TypedArrays doesn't look up Symbol.species. +features: [Symbol.species] +---*/ + +let throwOnGrossBufferConstruction = false; + +class GrossBuffer extends ArrayBuffer { + constructor() { + super(...arguments); + if (throwOnGrossBufferConstruction) { + throw new Test262Error("unreachable"); + } + } + static get [Symbol.species]() { + throw new Test262Error("unreachable"); + } +} + +let grossBuf = new GrossBuffer(1024); +throwOnGrossBufferConstruction = true; +let grossTA = new Uint8Array(grossBuf); +let mysteryTA = new Int8Array(grossTA); + +assert.sameValue(mysteryTA.buffer.__proto__, ArrayBuffer.prototype); +assert.sameValue(mysteryTA.buffer.constructor, ArrayBuffer); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js deleted file mode 100644 index 8ee2fba54bc..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with a different element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - ... - 19. Else, - a. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - b. If IsDetachedBuffer(srcData) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray, Symbol.species] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - var targetType = TA !== Int32Array ? Int32Array : Uint32Array; - new targetType(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js deleted file mode 100644 index 978f42af64b..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (C) 2017 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-typedarray-typedarray -description: > - When a TypedArray is created from another TypedArray with the same element-type - and SpeciesConstructor detaches the source buffer, AllocateArrayBuffer is still - executed. -info: | - 22.2.4.3 TypedArray ( typedArray ) - - ... - 16. If IsSharedArrayBuffer(srcData) is false, then - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - 18. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength, cloneConstructor ) - - ... - 3. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, srcLength). - 4. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError exception. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBufferPrototype%", - « [[ArrayBufferData]], [[ArrayBufferByteLength]] »). - ... -includes: [testTypedArray.js, detachArrayBuffer.js] -features: [TypedArray, Symbol.species] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var speciesCallCount = 0; - var bufferConstructor = Object.defineProperty({}, Symbol.species, { - get: function() { - speciesCallCount += 1; - $DETACHBUFFER(ta.buffer); - return speciesConstructor; - } - }); - - var prototypeCallCount = 0; - var speciesConstructor = Object.defineProperty(function(){}.bind(), "prototype", { - get: function() { - prototypeCallCount += 1; - return null; - } - }); - - var ta = new TA(0); - ta.buffer.constructor = bufferConstructor; - - assert.throws(TypeError, function() { - new TA(ta); - }, "TypeError thrown for detached source buffer"); - - assert.sameValue(speciesCallCount, 1, "@@species getter called once"); - assert.sameValue(prototypeCallCount, 1, "prototype getter called once"); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index b8976d696de..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testTypedArray.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - - Object.defineProperty(sample.buffer, "constructor", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js deleted file mode 100644 index 03860d1a7be..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testTypedArray.js] -features: [cross-realm, Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js deleted file mode 100644 index a510d7806da..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js deleted file mode 100644 index cfb79f1a948..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testTypedArray.js] -features: [Symbol, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ""; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol("1"); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js deleted file mode 100644 index 4b0b19aca73..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js deleted file mode 100644 index c485cae138f..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -var ctor = function() { - throw new Test262Error(); -}; -var m = { m() {} }.m; -ctor[Symbol.species] = m; - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - - sample.buffer.constructor = ctor; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js deleted file mode 100644 index 96ba9009d66..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-null.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on null buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = null; - var typedArray = new TA(sample); - - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), - ArrayBuffer.prototype, - "buffer ctor is not called when species is null" - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index 135634646b4..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - b. Let data be ? AllocateArrayBuffer(bufferConstructor, byteLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -var sample1 = new Int8Array(); -var sample2 = new Int16Array(); - -testWithTypedArrayConstructors(function(TA) { - var sample = TA === Int8Array ? sample2 : sample1; - var ctor = {}; - var called = 0; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() {called++;}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js deleted file mode 100644 index 32e78a37dcd..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-undefined.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 18. Else, - a. Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var OtherCtor = TA === Int8Array ? Int16Array : Int8Array; - var sample = new OtherCtor(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = undefined; - var a = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(a.buffer), - ArrayBuffer.prototype, - "buffer ctor is not called when species is undefined" - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js deleted file mode 100644 index 0aba12fc80f..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-different-type.js +++ /dev/null @@ -1,89 +0,0 @@ -// 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-typedarray-typedarray -description: > - Error when a TypedArray is created from another TypedArray with a different - element-type and SpeciesConstructor causes the "source" array to go - out-of-bounds. -includes: [testTypedArray.js, compareArray.js] -features: [TypedArray, Symbol.species, resizable-arraybuffer] ----*/ - -// If the host chooses to throw as allowed by the specification, the observed -// behavior will be identical to the case where `ArrayBuffer.prototype.resize` -// has not been implemented. The following assertion prevents this test from -// passing in runtimes which have not implemented the method. -assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); - -testWithTypedArrayConstructors(function(TA) { - var BPE = TA.BYTES_PER_ELEMENT; - var TargetCtor = TA !== Int32Array ? Int32Array : Uint32Array; - var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); - var speciesConstructor = Object.defineProperty(function(){}.bind(), 'prototype', { - get: function() { - return null; - } - }); - var onGetSpecies; - ab.constructor = Object.defineProperty({}, Symbol.species, { - get: function() { - onGetSpecies(); - return speciesConstructor; - } - }); - var source = new TA(ab, BPE); - var expected = [10, 20, 30]; - - source[0] = 10; - source[1] = 20; - source[2] = 30; - - onGetSpecies = function() { - try { - ab.resize(BPE * 5); - expected = [10, 20, 30, 0]; - } catch (_) {} - }; - - assert(compareArray(new TargetCtor(source), expected), 'following grow'); - - onGetSpecies = function() { - try { - ab.resize(BPE * 3); - expected = [10, 20]; - } catch (_) {} - }; - - assert(compareArray(new TargetCtor(source), expected), 'following shrink (within bounds)'); - - onGetSpecies = function() { - try { - ab.resize(BPE); - expected = []; - } catch (_) {} - }; - - assert(compareArray(new TargetCtor(source), expected), 'following shrink (on boundary)'); - - // `assert.throws` cannot be used in this case because the expected error - // is derived only after the constructor is invoked. - var expectedError; - var actualError; - onGetSpecies = function() { - try { - ab.resize(0); - expectedError = TypeError; - } catch (_) { - expectedError = Test262Error; - } - }; - try { - new TargetCtor(source); - throw new Test262Error('the operation completed successfully'); - } catch (caught) { - actualError = caught; - } - - assert.sameValue(actualError.constructor, expectedError); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js deleted file mode 100644 index c633ba06962..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/out-of-bounds-when-species-retrieved-same-type.js +++ /dev/null @@ -1,89 +0,0 @@ -// 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-typedarray-typedarray -description: > - Error when a TypedArray is created from another TypedArray with the same - element-type and SpeciesConstructor causes the "source" array to go - out-of-bounds. -includes: [testTypedArray.js, compareArray.js] -features: [TypedArray, Symbol.species, resizable-arraybuffer] ----*/ - -// If the host chooses to throw as allowed by the specification, the observed -// behavior will be identical to the case where `ArrayBuffer.prototype.resize` -// has not been implemented. The following assertion prevents this test from -// passing in runtimes which have not implemented the method. -assert.sameValue(typeof ArrayBuffer.prototype.resize, 'function'); - -testWithTypedArrayConstructors(function(TA) { - var BPE = TA.BYTES_PER_ELEMENT; - var ab = new ArrayBuffer(BPE * 4, {maxByteLength: BPE * 5}); - var speciesConstructor = Object.defineProperty(function(){}.bind(), 'prototype', { - get: function() { - return null; - } - }); - var onGetSpecies; - ab.constructor = Object.defineProperty({}, Symbol.species, { - get: function() { - onGetSpecies(); - return speciesConstructor; - } - }); - var source = new TA(ab, BPE); - var expected = [10, 20, 30]; - - source[0] = 10; - source[1] = 20; - source[2] = 30; - - onGetSpecies = function() { - try { - ab.resize(BPE * 5); - expected = [10, 20, 30, 0]; - } catch (_) {} - }; - - assert.sameValue((new TA(source)).join(','), expected.join(',')); - assert(compareArray(new TA(source), expected), 'following grow'); - - onGetSpecies = function() { - try { - ab.resize(BPE * 3); - expected = [10, 20]; - } catch (_) {} - }; - - assert(compareArray(new TA(source), expected), 'following shrink (within bounds)'); - - onGetSpecies = function() { - try { - ab.resize(BPE); - expected = []; - } catch (_) {} - }; - - assert(compareArray(new TA(source), expected), 'following shrink (on boundary)'); - - // `assert.throws` cannot be used in this case because the expected error - // is derived only after the constructor is invoked. - var expectedError; - var actualError; - onGetSpecies = function() { - try { - ab.resize(0); - expectedError = TypeError; - } catch (_) { - expectedError = Test262Error; - } - }; - try { - new TA(source); - throw new Test262Error('the operation completed successfully'); - } catch (caught) { - actualError = caught; - } - - assert.sameValue(actualError.constructor, expectedError); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js deleted file mode 100644 index f8e75d20916..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from getting typedArray argument's buffer.constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... -includes: [testTypedArray.js] -features: [TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - Object.defineProperty(sample.buffer, "constructor", { - get: function() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js deleted file mode 100644 index 43743b956e7..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Derive the ArrayBuffer prototype from the realm of the species constructor -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 9.1.14 GetPrototypeFromConstructor - - ... - 3. Let proto be ? Get(constructor, "prototype"). - 4. If Type(proto) is not Object, then - a. Let realm be ? GetFunctionRealm(constructor). - b. Let proto be realm's intrinsic object named intrinsicDefaultProto. - ... -includes: [testTypedArray.js] -features: [cross-realm, Symbol.species, TypedArray] ----*/ - -var other = $262.createRealm().global; -var C = new other.Function(); -C.prototype = null; - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = C; - - var typedArray = new TA(sample); - assert.sameValue( - Object.getPrototypeOf(typedArray.buffer), other.ArrayBuffer.prototype - ); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js deleted file mode 100644 index 7ed3aca0da1..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Use default ArrayBuffer constructor on undefined buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var called = 0; - var custom = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function() { - called++; - }; - - ctor[Symbol.species].prototype = custom; - - var typedArray = new TA(sample); - assert.sameValue(Object.getPrototypeOf(typedArray.buffer), custom); - assert.sameValue(called, 0); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js deleted file mode 100644 index 2072aa96dd1..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - 8. Throw a TypeError exception. -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - var m = { m() {} }; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = m; - - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js deleted file mode 100644 index b171826cfb1..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from buffer.constructor.@@species.prototype -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - 8. Let targetBuffer be ? AllocateArrayBuffer(cloneConstructor, cloneLength). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - 6. If S is either undefined or null, return defaultConstructor. - 7. If IsConstructor(S) is true, return S. - ... - - 24.1.1.1 AllocateArrayBuffer ( constructor, byteLength ) - - ... - 1. Let obj be ? OrdinaryCreateFromConstructor(constructor, - "%ArrayBufferPrototype%", « [[ArrayBufferData]], [[ArrayBufferByteLength]] » ) - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - - ctor[Symbol.species] = function(){}.bind(null); - Object.defineProperty(ctor[Symbol.species], "prototype", { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js deleted file mode 100644 index ec2aaf3c1f5..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt from getting typedArray argument's buffer.constructor.@@species -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 5. Let S be ? Get(C, @@species). - ... -includes: [testTypedArray.js] -features: [Symbol.species, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - var ctor = {}; - - sample.buffer.constructor = ctor; - Object.defineProperty(ctor, Symbol.species, { - get() { - throw new Test262Error(); - } - }); - - assert.throws(Test262Error, function() { - new TA(sample); - }); -}); diff --git a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js b/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js deleted file mode 100644 index ef97097495c..00000000000 --- a/test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (C) 2016 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-typedarray-typedarray -description: > - Return abrupt completion from typedArray argument's buffer.constructor's value -info: | - 22.2.4.3 TypedArray ( typedArray ) - - This description applies only if the TypedArray function is called with at - least one argument and the Type of the first argument is Object and that - object has a [[TypedArrayName]] internal slot. - - ... - 17. If SameValue(elementType, srcType) is true, then - a. Let data be ? CloneArrayBuffer(srcData, srcByteOffset). - ... - - 24.1.1.4 CloneArrayBuffer ( srcBuffer, srcByteOffset [ , cloneConstructor ] ) - - ... - 2. If cloneConstructor is not present, then - a. Let cloneConstructor be ? SpeciesConstructor(srcBuffer, %ArrayBuffer%). - ... - - 7.3.20 SpeciesConstructor ( O, defaultConstructor ) - - ... - 2. Let C be ? Get(O, "constructor"). - ... - 4. If Type(C) is not Object, throw a TypeError exception. - ... -includes: [testTypedArray.js] -features: [Symbol, TypedArray] ----*/ - -testWithTypedArrayConstructors(function(TA) { - var sample = new TA(); - - sample.buffer.constructor = 1; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = true; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = ''; - assert.throws(TypeError, function() { - new TA(sample); - }); - - sample.buffer.constructor = null; - assert.throws(TypeError, function() { - new TA(sample); - }); - - var s = Symbol('1'); - sample.buffer.constructor = s; - assert.throws(TypeError, function() { - new TA(sample); - }); -}); diff --git a/test/harness/temporalHelpers-one-shift-time-zone.js b/test/harness/temporalHelpers-one-shift-time-zone.js new file mode 100644 index 00000000000..db4e4102d0a --- /dev/null +++ b/test/harness/temporalHelpers-one-shift-time-zone.js @@ -0,0 +1,80 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + Verify the time zone arithmetic used in TemporalHelpers.oneShiftTimeZone() + against known cases in the implementation's time zone database +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +function checkTimeZoneArithmetic(shiftInstant, shiftNs, realTimeZoneName, shiftWallTime) { + // No need to test this on hosts that don't provide an Intl object. It's + // sufficient that the logic is tested on at least one host. + if (typeof globalThis.Intl === "undefined") + return; + + const tz = TemporalHelpers.oneShiftTimeZone(shiftInstant, shiftNs); + const realTz = new Temporal.TimeZone(realTimeZoneName); + + assert.sameValue( + tz.getOffsetNanosecondsFor(shiftInstant), + realTz.getOffsetNanosecondsFor(shiftInstant), + 'offset at shift instant' + ); + const minus1 = shiftInstant.subtract({ hours: 1 }); + assert.sameValue( + tz.getOffsetNanosecondsFor(minus1), + realTz.getOffsetNanosecondsFor(minus1), + 'offset at 1 hour before shift' + ); + const plus1 = shiftInstant.add({ hours: 1 }); + assert.sameValue( + tz.getOffsetNanosecondsFor(plus1), + realTz.getOffsetNanosecondsFor(plus1), + 'offset at 1 hour after shift' + ); + + assert.compareArray( + tz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(shiftWallTime).map((i) => i.epochNanoseconds), + 'possible instants for wall time' + ); + const before1 = shiftWallTime.subtract({ hours: 1 }); + assert.compareArray( + tz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds), + 'possible instants for 1 hour before wall time' + ); + const after1 = shiftWallTime.add({ hours: 1 }); + assert.compareArray( + tz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds), + realTz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds), + 'possible instants for 1 hour after wall time' + ); +} + +// Check a positive DST shift from +00:00 to +01:00 +checkTimeZoneArithmetic( + new Temporal.Instant(1616893200000000000n), + 3600e9, + 'Europe/London', + new Temporal.PlainDateTime(2021, 3, 28, 1) +); + +// Check a negative DST shift from +00:00 to -01:00 +checkTimeZoneArithmetic( + new Temporal.Instant(1635642000000000000n), + -3600e9, + 'Atlantic/Azores', + new Temporal.PlainDateTime(2021, 10, 31, 1) +); + +// Check the no-shift case +checkTimeZoneArithmetic( + new Temporal.Instant(0n), + 0, + 'UTC', + new Temporal.PlainDateTime(1970, 1, 1) +); diff --git a/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js b/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js index 1274a0daac7..e92266498e4 100644 --- a/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js +++ b/test/intl402/NumberFormat/constructor-roundingIncrement-invalid.js @@ -1,4 +1,5 @@ // Copyright 2021 the V8 project authors. All rights reserved. +// Copyright (C) 2022 Igalia, S.L. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- esid: sec-initializenumberformat @@ -26,14 +27,18 @@ assert.throws(RangeError, function() { new Intl.NumberFormat([], {roundingIncrement: 5001}); }, '5001'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'morePrecision'}); }, '2, roundingType is "morePrecision"'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, roundingPriority: 'lessPrecision'}); }, '2, roundingType is "lessPrecision"'); -assert.throws(RangeError, function() { +assert.throws(TypeError, function() { new Intl.NumberFormat([], {roundingIncrement: 2, minimumSignificantDigits: 1}); }, '2, roundingType is "significantDigits"'); + +assert.throws(RangeError, function() { + new Intl.NumberFormat([], {roundingIncrement: 2, maximumFractionDigits:3 , minimumFractionDigits:2 }); +}, '"maximumFractionDigits" is not equal to "minimumFractionDigits"'); diff --git a/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js b/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js new file mode 100644 index 00000000000..b7a6b5c0bc1 --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/era/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.era +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.era(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js b/test/intl402/Temporal/Calendar/prototype/era/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..eb1e61d9b19 --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/era/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.era +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.era({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js b/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js new file mode 100644 index 00000000000..6b3f65b9ea4 --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/eraYear/argument-string-invalid.js @@ -0,0 +1,61 @@ +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.calendar.prototype.erayear +description: > + RangeError thrown if an invalid ISO string (or syntactically valid ISO string + that is not supported) is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + // invalid ISO strings: + "", + "invalid iso8601", + "2020-01-00", + "2020-01-32", + "2020-02-30", + "2021-02-29", + "2020-00-01", + "2020-13-01", + "2020-01-01T", + "2020-01-01T25:00:00", + "2020-01-01T01:60:00", + "2020-01-01T01:60:61", + "2020-01-01junk", + "2020-01-01T00:00:00junk", + "2020-01-01T00:00:00+00:00junk", + "2020-01-01T00:00:00+00:00[UTC]junk", + "2020-01-01T00:00:00+00:00[UTC][u-ca=iso8601]junk", + "02020-01-01", + "2020-001-01", + "2020-01-001", + "2020-01-01T001", + "2020-01-01T01:001", + "2020-01-01T01:01:001", + // valid, but forms not supported in Temporal: + "2020-W01-1", + "2020-001", + "+0002020-01-01", + // valid, but this calendar must not exist: + "2020-01-01[u-ca=notexist]", + // may be valid in other contexts, but insufficient information for PlainDate: + "2020-01", + "+002020-01", + "01-01", + "2020-W01", + "P1Y", + "-P12Y", + // valid, but outside the supported range: + "-999999-01-01", + "+999999-01-01", +]; +const instance = new Temporal.Calendar("iso8601"); +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.eraYear(arg), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} diff --git a/test/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js b/test/intl402/Temporal/Calendar/prototype/eraYear/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 00000000000..a2c9fa6645e --- /dev/null +++ b/test/intl402/Temporal/Calendar/prototype/eraYear/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.erayear +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.eraYear({ year: 2000, month: 5, day: 3, calendar }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1); diff --git a/test/intl402/Temporal/Instant/prototype/toString/timezone-offset.js b/test/intl402/Temporal/Instant/prototype/toString/timezone-offset.js new file mode 100644 index 00000000000..ee2bd1e5fba --- /dev/null +++ b/test/intl402/Temporal/Instant/prototype/toString/timezone-offset.js @@ -0,0 +1,19 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.instant.prototype.tostring +description: The time zone offset part of the string serialization (Intl time zones) +features: [BigInt, Temporal] +---*/ + +const instant = new Temporal.Instant(0n); + +function test(timeZoneIdentifier, expected, description) { + const timeZone = new Temporal.TimeZone(timeZoneIdentifier); + assert.sameValue(instant.toString({ timeZone }), expected, description); +} + +test("Europe/Berlin", "1970-01-01T01:00:00+01:00", "positive offset"); +test("America/New_York", "1969-12-31T19:00:00-05:00", "negative offset"); +test("Africa/Monrovia", "1969-12-31T23:15:30-00:45", "sub-minute offset"); diff --git a/test/intl402/Temporal/TimeZone/etc-timezone.js b/test/intl402/Temporal/TimeZone/etc-timezone.js new file mode 100644 index 00000000000..b3995e5f4ca --- /dev/null +++ b/test/intl402/Temporal/TimeZone/etc-timezone.js @@ -0,0 +1,79 @@ +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.timezone +description: Some Etc/GMT{+/-}{0}N timezones are valid, but not all +features: [Temporal] +---*/ + +// "Etc/GMT-0" through "Etc/GMT-14" are OK + +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT-0")).toString(), + "UTC", // if the offset is -0, we say "UTC" rather than "GMT" + "Etc/GMT-0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12,13,14].forEach((n) => { + let tz = "Etc/GMT-" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtMinus24TZ = "Etc/GMT-24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtMinus24TZ); }, + gmtMinus24TZ + " is an invalid timezone" +); + +// "Etc/GMT-0N" is not OK (1 ≤ N ≤ 9) +[1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT-0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// "Etc/GMT+0N" is not OK (0 ≤ N ≤ 9) +[0,1,2,3,4,5,6,7,8,9].forEach((n) => { + let tz = "Etc/GMT+0" + n; + assert.throws( + RangeError, + () => { new Temporal.TimeZone(tz); }, + tz + " is an invalid timezone" + ); +}); + +// Etc/GMT+0" through "Etc/GMT+12" are OK + +// zero is handled in its own way (say "UTC" rather than "GMT"): +assert.sameValue( + (new Temporal.TimeZone("Etc/GMT+0")).toString(), + "UTC", // if the offset is +0, we say "UTC" rather than "GMT" + "Etc/GMT+0 is a valid timezone" +); + +[1,2,3,4,5,6,7,8,9,10,11,12].forEach((n) => { + let tz = "Etc/GMT+" + n; + let instance = new Temporal.TimeZone(tz); + assert.sameValue( + instance.toString(), + tz, + tz + " is a valid timezone" + ); +}); + +let gmtPlus24TZ = "Etc/GMT+24"; +assert.throws( + RangeError, + () => { new Temporal.TimeZone(gmtPlus24TZ); }, + gmtPlus24TZ + " is an invalid timezone" +); diff --git a/test/language/expressions/unary-plus/S11.4.6_A3_T3.js b/test/language/expressions/unary-plus/S11.4.6_A3_T3.js index 79bf732a2f2..9a3a2f6b49f 100644 --- a/test/language/expressions/unary-plus/S11.4.6_A3_T3.js +++ b/test/language/expressions/unary-plus/S11.4.6_A3_T3.js @@ -13,11 +13,21 @@ if (+"1" !== 1) { } //CHECK#2 -if (isNaN(+"x") !== true) { - throw new Test262Error('#2: +"x" === Not-a-Number. Actual: ' + (+"x")); +if (+new Number("-1") !== -1) { + throw new Test262Error('#2: +new String("-1") === -1. Actual: ' + (+new String("-1"))); } //CHECK#3 -if (+new Number("-1") !== -1) { - throw new Test262Error('#3: +new String("-1") === -1. Actual: ' + (+new String("-1"))); +if (isNaN(+"x") !== true) { + throw new Test262Error('#3: +"x" === Not-a-Number. Actual: ' + (+"x")); +} + +//CHECK#4 +if (isNaN(+"INFINITY") !== true) { + throw new Test262Error('#4: +"INFINITY" === Not-a-Number. Actual: ' + (+"INFINITY")); +} + +//CHECK#5 +if (isNaN(+"infinity") !== true) { + throw new Test262Error('#5: +"infinity" === Not-a-Number. Actual: ' + (+"infinity")); } diff --git a/test/language/statements/for-in/S12.6.4_A7_T2.js b/test/language/statements/for-in/S12.6.4_A7_T2.js index 4ae8a3946ec..b7043d78b4a 100644 --- a/test/language/statements/for-in/S12.6.4_A7_T2.js +++ b/test/language/statements/for-in/S12.6.4_A7_T2.js @@ -13,7 +13,10 @@ description: > var __obj, __accum; -__obj={aa:1,ba:2,ca:3}; +__obj = Object.create(null); +__obj.aa = 1; +__obj.ba = 2; +__obj.ca = 3; __accum=""; @@ -25,23 +28,10 @@ for (var __key in __obj){ } - -////////////////////////////////////////////////////////////////////////////// -//CHECK#1 -if (!((__accum.indexOf("aa1")!==-1)&&(__accum.indexOf("ca3")!==-1))) { - throw new Test262Error('#1: (__accum.indexOf("aa1")!==-1)&&(__accum.indexOf("ca3")!==-1)'); -} -// -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -//CHECK#2 -if (__accum.indexOf("ba2")!==-1) { - throw new Test262Error('#2: __accum.indexOf("ba2") === -1. Actual: __accum.indexOf("ba2") ==='+ __accum.indexOf("ba2") ); -} -// -////////////////////////////////////////////////////////////////////////////// - +assert( + __accum === "aa1ca3" || __accum === "ca3aa1", + "Unexpected value: '" + __accum + "'" +); // erasator is the hash map terminator function erasator_T_1000(hash_map, charactr){