diff options
Diffstat (limited to 'js/src/tests/test262/built-ins/Temporal/PlainTime')
628 files changed, 18205 insertions, 0 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js new file mode 100644 index 0000000000..fad1f11b39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/basic.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Basic tests for the PlainTime constructor. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [15, 23, 30, 123, 456, 789]; +const plainTime = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(plainTime, ...args); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js new file mode 100644 index 0000000000..26de31a9aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/builtin.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Tests that Temporal.PlainTime meets the requirements for built-in objects +info: | + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime), + Function.prototype, "prototype"); + +assert.sameValue(typeof Temporal.PlainTime.prototype, + "object", "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js new file mode 100644 index 0000000000..d253be6629 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-cast.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: compare() casts its arguments +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); + +assert.sameValue(Temporal.PlainTime.compare({ hour: 16, minute: 34 }, t2), 1, "one object"); +assert.sameValue(Temporal.PlainTime.compare("16:34", t2), 1, "one string"); +assert.throws(TypeError, () => Temporal.PlainTime.compare({ hours: 16 }, t2), "one missing property"); + +assert.sameValue(Temporal.PlainTime.compare(t1, { hour: 16, minute: 34 }), -1, "two object"); +assert.sameValue(Temporal.PlainTime.compare(t1, "16:34"), -1, "two string"); +assert.throws(TypeError, () => Temporal.PlainTime.compare(t1, { hours: 16 }), "two missing property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-number.js new file mode 100644 index 0000000000..91e29a6769 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-number.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: A number is invalid in place of an ISO string for Temporal.PlainTime +features: [Temporal] +---*/ + +const numbers = [ + 1, + -123456.987654321, + 1234567, + 123456.9876543219, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `A number (${arg}) is not a valid ISO string for PlainTime (first argument)` + ); + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `A number (${arg}) is not a valid ISO string for PlainTime (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..7d2b108223 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-calendar-annotation.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[u-ca=iso8601]", "without time zone"], + ["12:34:56.987654321[UTC][u-ca=iso8601]", "with time zone"], + ["12:34:56.987654321[!u-ca=iso8601]", "with ! and no time zone"], + ["12:34:56.987654321[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["T12:34:56.987654321[u-ca=iso8601]", "with T and no time zone"], + ["T12:34:56.987654321[UTC][u-ca=iso8601]", "with T and time zone"], + ["T12:34:56.987654321[!u-ca=iso8601]", "with T, !, and no time zone"], + ["T12:34:56.987654321[UTC][!u-ca=iso8601]", "with T, !, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601]", "with date and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][u-ca=iso8601]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[!u-ca=iso8601]", "with !, date, and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][!u-ca=iso8601]", "with !, date, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.compare(arg, arg); + + assert.sameValue( + result, + 0, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..d553e57b96 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-critical-unknown-annotation.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[!foo=bar]", + "T00:00[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `reject unknown annotation with critical flag: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `reject unknown annotation with critical flag: ${arg} (second argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..08ceab76c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-date-with-utc-offset.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.compare +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const validStrings = [ + "12:34:56.987654321+00:00", + "12:34:56.987654321+00:00[UTC]", + "12:34:56.987654321+00:00[!UTC]", + "12:34:56.987654321-02:30[America/St_Johns]", + "1976-11-18T12:34:56.987654321+00:00", + "1976-11-18T12:34:56.987654321+00:00[UTC]", + "1976-11-18T12:34:56.987654321+00:00[!UTC]", + "1976-11-18T12:34:56.987654321-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = Temporal.PlainTime.compare(arg, arg); + + assert.sameValue( + result, + 0, + `"${arg}" is a valid UTC offset with time for PlainTime` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `"${arg}" UTC offset without time is not valid for PlainTime (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `"${arg}" UTC offset without time is not valid for PlainTime (second argument)` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..5ce6745e94 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-calendar.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[u-ca=iso8601][!u-ca=iso8601]", + "00:00[!u-ca=iso8601][u-ca=iso8601]", + "00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `reject more than one calendar annotation if any critical: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `reject more than one calendar annotation if any critical: ${arg} (first argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..2343613c5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-multiple-time-zone.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[UTC][UTC]", + "T00:00[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `reject more than one time zone annotation: ${arg} (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `reject more than one time zone annotation: ${arg} (second argument)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js new file mode 100644 index 0000000000..67e51e9a45 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-no-implicit-midnight.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const midnight = new Temporal.PlainTime(); +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + "Date-only string throws, does not implicitly convert to midnight (first argument)" +); +assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + "Date-only string throws, does not implicitly convert to midnight (second argument)" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 0000000000..d6a099db5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: ISO 8601 time designator "T" required in cases of ambiguity +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const midnight = new Temporal.PlainTime(); + +TemporalHelpers.ISO.plainTimeStringsAmbiguous().forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + `'${arg}' is ambiguous and requires T prefix (first argument)` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + `'${arg}' is ambiguous and requires T prefix (second argument)` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + Temporal.PlainTime.compare(arg, midnight); + Temporal.PlainTime.compare(midnight, arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, midnight), + `space is not accepted as a substitute for T prefix (first argument): '${arg}'` + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(midnight, arg), + `space is not accepted as a substitute for T prefix (second argument): '${arg}'` + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +TemporalHelpers.ISO.plainTimeStringsUnambiguous().forEach((arg) => { + Temporal.PlainTime.compare(arg, midnight); + Temporal.PlainTime.compare(midnight, arg); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-separators.js new file mode 100644 index 0000000000..d98f91a43a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-separators.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const tests = [ + ["1976-11-18T12:34:56.987654321", "uppercase T"], + ["1976-11-18t12:34:56.987654321", "lowercase T"], + ["1976-11-18 12:34:56.987654321", "space between date and time"], + ["T12:34:56.987654321", "time-only uppercase T"], + ["t12:34:56.987654321", "time-only lowercase T"], +]; + +tests.forEach(([arg, description]) => { + assert.sameValue( + Temporal.PlainTime.compare(arg, plainTime), + 0, + `variant time separators (${description}), first argument` + ); + + assert.sameValue( + Temporal.PlainTime.compare(plainTime, arg), + 0, + `variant time separators (${description}), second argument` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..272daa9d91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-time-zone-annotation.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[Asia/Kolkata]", "named, with no offset"], + ["12:34:56.987654321[!Europe/Vienna]", "named, with ! and no offset"], + ["12:34:56.987654321[+00:00]", "numeric, with no offset"], + ["12:34:56.987654321[!-02:30]", "numeric, with ! and no offset"], + ["T12:34:56.987654321[UTC]", "named, with T and no offset"], + ["T12:34:56.987654321[!Africa/Abidjan]", "named, with T, !, and no offset"], + ["T12:34:56.987654321[+01:00]", "numeric, with T and no offset"], + ["T12:34:56.987654321[!-08:00]", "numeric, with T, !, and no offset"], + ["12:34:56.987654321+00:00[America/Sao_Paulo]", "named, with offset"], + ["12:34:56.987654321+00:00[!Asia/Tokyo]", "named, with ! and offset"], + ["12:34:56.987654321+00:00[-02:30]", "numeric, with offset"], + ["12:34:56.987654321+00:00[!+00:00]", "numeric, with ! and offset"], + ["T12:34:56.987654321+00:00[America/New_York]", "named, with T and offset"], + ["T12:34:56.987654321+00:00[!UTC]", "named, with T, !, and offset"], + ["T12:34:56.987654321+00:00[-08:00]", "numeric, with T and offset"], + ["T12:34:56.987654321+00:00[!+01:00]", "numeric, with T, !, and offset"], + ["1970-01-01T12:34:56.987654321[Africa/Lagos]", "named, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!America/Vancouver]", "named, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321[+00:00]", "numeric, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!-02:30]", "numeric, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321+00:00[Europe/London]", "named, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!Asia/Seoul]", "named, with date, offset, and !"], + ["1970-01-01T12:34:56.987654321+00:00[+01:00]", "numeric, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!-08:00]", "numeric, with date, offset, and !"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.compare(arg, arg); + + assert.sameValue( + result, + 0, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..ddfba8993f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-unknown-annotation.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[foo=bar]", "alone"], + ["12:34:56.987654321[UTC][foo=bar]", "with time zone"], + ["12:34:56.987654321[u-ca=iso8601][foo=bar]", "with calendar"], + ["12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["T12:34:56.987654321[foo=bar]", "with T"], + ["T12:34:56.987654321[UTC][foo=bar]", "with T and time zone"], + ["T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with T and calendar"], + ["T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with T, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar]", "with date"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with date and calendar"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with date, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.compare(arg, arg); + + assert.sameValue( + result, + 0, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js new file mode 100644 index 0000000000..3bfde29db9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const halfPast = new Temporal.PlainTime(0, 30); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + assert.sameValue(Temporal.PlainTime.compare(arg, halfPast), 0, `T prefix is accepted: ${arg} (first argument)`); + assert.sameValue(Temporal.PlainTime.compare(halfPast, arg), 0, `T prefix is accepted: ${arg} (second argument)`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..abff07e6ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-string-with-utc-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", + "09:00:00Z[UTC]", + "09:00:00Z", +]; +const plainTime = new Temporal.PlainTime(); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, plainTime), + "String with UTC designator should not be valid as a PlainTime (first argument)" + ); + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(plainTime, arg), + "String with UTC designator should not be valid as a PlainTime (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-wrong-type.js new file mode 100644 index 0000000000..225a8d16c9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-wrong-type.js @@ -0,0 +1,47 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.compare +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainTime +features: [BigInt, Symbol, Temporal] +---*/ + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), + `${description} does not convert to a valid ISO string (first argument)` + ); + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), + `${description} does not convert to a valid ISO string (second argument)` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainTime, "Temporal.PlainTime, object"], + [Temporal.PlainTime.prototype, "Temporal.PlainTime.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => Temporal.PlainTime.compare(arg, new Temporal.PlainTime(12, 34, 56, 987, 654, 321)), `${description} is not a valid property bag and does not convert to a string (first argument)`); + assert.throws(TypeError, () => Temporal.PlainTime.compare(new Temporal.PlainTime(12, 34, 56, 987, 654, 321), arg), `${description} is not a valid property bag and does not convert to a string (second argument)`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 0000000000..55145852e3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); +const time = new Temporal.PlainTime(16, 50, 35, 0, 0, 1); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result1 = Temporal.PlainTime.compare(time, datetime); +assert.sameValue(result1, 0); + +const result2 = Temporal.PlainTime.compare(datetime, time); +assert.sameValue(result2, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..13008889fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, Infinity, -Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(RangeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..c16b088148 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(datetime, time), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); + assert.throws( + TypeError, + () => Temporal.PlainTime.compare(time, datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..53767252b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(RangeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..22209b6693 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(TypeError, () => Temporal.PlainTime.compare(datetime, time)); + assert.throws(TypeError, () => Temporal.PlainTime.compare(time, datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js new file mode 100644 index 0000000000..212dc43f85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/basic.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Basic tests for compare() +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t1bis = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); + +assert.sameValue(Temporal.PlainTime.compare(t1, t1), 0, "same object"); +assert.sameValue(Temporal.PlainTime.compare(t1, t1bis), 0, "different object"); +assert.sameValue(Temporal.PlainTime.compare(t1, t2), -1, "before"); +assert.sameValue(Temporal.PlainTime.compare(t2, t1), 1, "after"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js new file mode 100644 index 0000000000..3d5821934a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Tests that Temporal.PlainTime.compare meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.compare), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.compare), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.compare), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.compare.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/exhaustive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/exhaustive.js new file mode 100644 index 0000000000..d711fce237 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/exhaustive.js @@ -0,0 +1,119 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Tests for compare() with each possible outcome +features: [Temporal] +---*/ + +const cal1 = "iso8601"; +const cal2 = new (class extends Temporal.Calendar { id = "custom"; })("iso8601"); + +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 45, 333, 777, 111, cal1), + new Temporal.PlainTime(6, 15, 45, 333, 777, 111, cal2) + ), + 1, + "hour >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 15, 222, 444, 6, cal1), + new Temporal.PlainTime(22, 30, 15, 222, 444, 6, cal2) + ), + -1, + "hour <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 45, 15, 333, 777, 111, cal1), + new Temporal.PlainTime(12, 15, 22, 333, 777, 111, cal2) + ), + 1, + "minute >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 15, 222, 444, 6, cal1), + new Temporal.PlainTime(6, 57, 15, 222, 444, 6, cal2) + ), + -1, + "minute <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 6, 333, 777, 111, cal1), + new Temporal.PlainTime(12, 15, 5, 333, 777, 111, cal2) + ), + 1, + "second >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 3, 222, 444, 6, cal1), + new Temporal.PlainTime(6, 30, 4, 222, 444, 6, cal2) + ), + -1, + "second <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 45, 6, 777, 111, cal1), + new Temporal.PlainTime(12, 15, 45, 5, 777, 111, cal2) + ), + 1, + "millisecond >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 15, 3, 444, 6, cal1), + new Temporal.PlainTime(6, 30, 15, 4, 444, 6, cal2) + ), + -1, + "millisecond <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 45, 333, 6, 111, cal1), + new Temporal.PlainTime(12, 15, 45, 333, 5, 111, cal2) + ), + 1, + "microsecond >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 15, 222, 3, 6, cal1), + new Temporal.PlainTime(6, 30, 15, 222, 4, 6, cal2) + ), + -1, + "microsecond <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 45, 333, 777, 999, cal1), + new Temporal.PlainTime(12, 15, 45, 333, 777, 111, cal2) + ), + 1, + "nanosecond >" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(6, 30, 15, 222, 444, 0, cal1), + new Temporal.PlainTime(6, 30, 15, 222, 444, 6, cal2) + ), + -1, + "nanosecond <" +); +assert.sameValue( + Temporal.PlainTime.compare( + new Temporal.PlainTime(12, 15, 45, 333, 777, 111, cal1), + new Temporal.PlainTime(12, 15, 45, 333, 777, 111, cal2) + ), + 0, + "=" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/leap-second.js new file mode 100644 index 0000000000..d9d9b320dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Leap second is a valid ISO string for PlainTime +features: [Temporal] +---*/ + +let arg = "2016-12-31T23:59:60"; +const result1 = Temporal.PlainTime.compare(arg, new Temporal.PlainTime(23, 59, 59)); +assert.sameValue(result1, 0, "leap second is a valid ISO string for PlainTime (first argument)"); +const result2 = Temporal.PlainTime.compare(new Temporal.PlainTime(23, 59, 59), arg); +assert.sameValue(result2, 0, "leap second is a valid ISO string for PlainTime (first argument)"); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result3 = Temporal.PlainTime.compare(arg, new Temporal.PlainTime(23, 59, 59)); +assert.sameValue(result3, 0, "second: 60 is ignored in property bag for PlainTime (first argument)"); +const result4 = Temporal.PlainTime.compare(new Temporal.PlainTime(23, 59, 59), arg); +assert.sameValue(result4, 0, "second: 60 is ignored in property bag for PlainTime (second argument)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js new file mode 100644 index 0000000000..e917ed6a97 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare.length is 2 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.compare, "length", { + value: 2, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js new file mode 100644 index 0000000000..ab741acddb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare.name is "compare" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.compare, "name", { + value: "compare", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js new file mode 100644 index 0000000000..849f81c831 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Temporal.PlainTime.compare does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.compare(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.compare), false, + "isConstructor(Temporal.PlainTime.compare)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js new file mode 100644 index 0000000000..24afb94488 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/plaintime-propertybag-no-time-units.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const props = {}; +assert.throws(TypeError, () => Temporal.PlainTime.compare(props, new Temporal.PlainTime(0, 30)), "TypeError if no properties are present"); + +props.minute = 30; +const result = Temporal.PlainTime.compare(props, new Temporal.PlainTime(0, 30)); +assert.sameValue(result, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js new file mode 100644 index 0000000000..03225cf214 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: The "compare" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.compare, + "function", + "`typeof PlainTime.compare` is `function`" +); + +verifyProperty(Temporal.PlainTime, "compare", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js new file mode 100644 index 0000000000..67cee1bbca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/use-internal-slots.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-comparetemporaltime +description: compare() ignores the observable properties and uses internal slots +features: [Temporal] +---*/ + +function CustomError() {} + +class AvoidGettersTime extends Temporal.PlainTime { + get hour() { + throw new CustomError(); + } + get minute() { + throw new CustomError(); + } + get second() { + throw new CustomError(); + } + get millisecond() { + throw new CustomError(); + } + get microsecond() { + throw new CustomError(); + } + get nanosecond() { + throw new CustomError(); + } +} + +const one = new AvoidGettersTime(12, 34, 56, 987, 654, 321); +const two = new AvoidGettersTime(6, 54, 32, 123, 456, 789); +assert.sameValue(Temporal.PlainTime.compare(one, two), 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js new file mode 100644 index 0000000000..5ec802a047 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/compare/year-zero.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.compare +description: Negative zero, as an extended year, fails +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00", + "-000000-12-07T03:24:30+00:00[UTC]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(arg, time), + "Cannot use minus zero as extended year (first argument)" + ); + + assert.throws( + RangeError, + () => Temporal.PlainTime.compare(time, arg), + "Cannot use minus zero as extended year (second argument)" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js new file mode 100644 index 0000000000..85b3df5864 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/constructor.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime constructor cannot be called as a function +info: | + 1. If NewTarget is undefined, throw a TypeError exception. +features: [Temporal] +---*/ + +assert.throws(TypeError, () => Temporal.PlainTime(12, 0, 0)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js new file mode 100644 index 0000000000..38a4faf253 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-number.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: A number is invalid in place of an ISO string for Temporal.PlainTime +features: [Temporal] +---*/ + +const numbers = [ + 1, + -123456.987654321, + 1234567, + 123456.9876543219, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => Temporal.PlainTime.from(arg), + `A number (${arg}) is not a valid ISO string for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js new file mode 100644 index 0000000000..edf7e02e9b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object-leap-second.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Object argument handles leap seconds according to the overflow option. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const options of [undefined, {}, { overflow: "constrain" }]) { + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60 }, options), + 23, 59, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 12, minute: 30, second: 60 }, options), + 12, 30, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60, millisecond: 170 }, options), + 23, 59, 59, 170, 0, 0); +} + +const options = { overflow: "reject" }; +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60 }, options)); +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 12, minute: 30, second: 60 }, options)); +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 23, minute: 59, second: 60, millisecond: 170 }, options)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js new file mode 100644 index 0000000000..56a7af892e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-object.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Plain object argument is supported and ignores plural properties +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 15, minute: 23 }), + 15, 23, 0, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ minute: 30, microsecond: 555 }), + 0, 30, 0, 0, 555, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ year: 2019, month: 10, day: 1, hour: 14, minute: 20, second: 36 }), + 14, 20, 36, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hours: 2, minute: 30, microsecond: 555 }), + 0, 30, 0, 0, 555, 0); + +assert.throws(TypeError, () => Temporal.PlainTime.from({})); +assert.throws(TypeError, () => Temporal.PlainTime.from({ minutes: 12 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js new file mode 100644 index 0000000000..920c3150ac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaindatetime.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Fast path for converting Temporal.PlainDateTime to Temporal.PlainTime by reading internal slots +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((plainDateTime) => { + const result = Temporal.PlainTime.from(plainDateTime); + TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 321); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js new file mode 100644 index 0000000000..33fe44b8d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-plaintime.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: A PlainTime object is copied, not returned directly +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const orig = new Temporal.PlainTime(11, 42, 0, 0, 0, 0); +const result = Temporal.PlainTime.from(orig); + +TemporalHelpers.assertPlainTime( + result, + 11, 42, 0, 0, 0, 0, + "PlainTime is copied" +); + +assert.notSameValue( + result, + orig, + "When a PlainTime is given, the returned value is not the original PlainTime" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..917b78d3ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-calendar-annotation.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[u-ca=iso8601]", "without time zone"], + ["12:34:56.987654321[UTC][u-ca=iso8601]", "with time zone"], + ["12:34:56.987654321[!u-ca=iso8601]", "with ! and no time zone"], + ["12:34:56.987654321[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["T12:34:56.987654321[u-ca=iso8601]", "with T and no time zone"], + ["T12:34:56.987654321[UTC][u-ca=iso8601]", "with T and time zone"], + ["T12:34:56.987654321[!u-ca=iso8601]", "with T, !, and no time zone"], + ["T12:34:56.987654321[UTC][!u-ca=iso8601]", "with T, !, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601]", "with date and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][u-ca=iso8601]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[!u-ca=iso8601]", "with !, date, and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][!u-ca=iso8601]", "with !, date, and time zone"], + ["12:34:56.987654321[u-ca=hebrew]", "calendar annotation ignored"], + ["12:34:56.987654321[u-ca=unknown]", "calendar annotation ignored even if unknown calendar"], + ["12:34:56.987654321[!u-ca=unknown]", "calendar annotation ignored even if unknown calendar with !"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.from(arg); + + TemporalHelpers.assertPlainTime( + result, + 12, 34, 56, 987, 654, 321, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..ed8825b591 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-critical-unknown-annotation.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[!foo=bar]", + "T00:00[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..d715e51791 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-date-with-utc-offset.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const validStrings = [ + "12:34:56.987654321+00:00", + "12:34:56.987654321+00:00[UTC]", + "12:34:56.987654321+00:00[!UTC]", + "12:34:56.987654321-02:30[America/St_Johns]", + "1976-11-18T12:34:56.987654321+00:00", + "1976-11-18T12:34:56.987654321+00:00[UTC]", + "1976-11-18T12:34:56.987654321+00:00[!UTC]", + "1976-11-18T12:34:56.987654321-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = Temporal.PlainTime.from(arg); + + TemporalHelpers.assertPlainTime( + result, + 12, 34, 56, 987, 654, 321, + `"${arg}" is a valid UTC offset with time for PlainTime` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `"${arg}" UTC offset without time is not valid for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js new file mode 100644 index 0000000000..ef9582da8b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-leap-second.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Leap second is replaced by :59 in ISO strings. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const options of [undefined, {}, { overflow: "constrain" }, { overflow: "reject" }]) { + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:59:60", options), + 23, 59, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("12:30:60", options), + 12, 30, 59, 0, 0, 0); + TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:59:60.170", options), + 23, 59, 59, 170, 0, 0); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..3e3f964b70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[u-ca=iso8601][!u-ca=iso8601]", + "00:00[!u-ca=iso8601][u-ca=iso8601]", + "00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..6ed71fbbc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-multiple-time-zone.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[UTC][UTC]", + "T00:00[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js new file mode 100644 index 0000000000..3555c8f350 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-no-implicit-midnight.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 0000000000..30a22c3072 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: ISO 8601 time designator "T" required in cases of ambiguity +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +TemporalHelpers.ISO.plainTimeStringsAmbiguous().forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `'${arg}' is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + Temporal.PlainTime.from(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + `space is not accepted as a substitute for T prefix: '${arg}'` + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +TemporalHelpers.ISO.plainTimeStringsUnambiguous().forEach( + (arg) => Temporal.PlainTime.from(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-separators.js new file mode 100644 index 0000000000..2e2645a48e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-separators.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["1976-11-18T12:34:56.987654321", "uppercase T"], + ["1976-11-18t12:34:56.987654321", "lowercase T"], + ["1976-11-18 12:34:56.987654321", "space between date and time"], + ["T12:34:56.987654321", "time-only uppercase T"], + ["t12:34:56.987654321", "time-only lowercase T"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.from(arg); + + TemporalHelpers.assertPlainTime( + result, + 12, 34, 56, 987, 654, 321, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..6459e18647 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-time-zone-annotation.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[Asia/Kolkata]", "named, with no offset"], + ["12:34:56.987654321[!Europe/Vienna]", "named, with ! and no offset"], + ["12:34:56.987654321[+00:00]", "numeric, with no offset"], + ["12:34:56.987654321[!-02:30]", "numeric, with ! and no offset"], + ["T12:34:56.987654321[UTC]", "named, with T and no offset"], + ["T12:34:56.987654321[!Africa/Abidjan]", "named, with T, !, and no offset"], + ["T12:34:56.987654321[+01:00]", "numeric, with T and no offset"], + ["T12:34:56.987654321[!-08:00]", "numeric, with T, !, and no offset"], + ["12:34:56.987654321+00:00[America/Sao_Paulo]", "named, with offset"], + ["12:34:56.987654321+00:00[!Asia/Tokyo]", "named, with ! and offset"], + ["12:34:56.987654321+00:00[-02:30]", "numeric, with offset"], + ["12:34:56.987654321+00:00[!+00:00]", "numeric, with ! and offset"], + ["T12:34:56.987654321+00:00[America/New_York]", "named, with T and offset"], + ["T12:34:56.987654321+00:00[!UTC]", "named, with T, !, and offset"], + ["T12:34:56.987654321+00:00[-08:00]", "numeric, with T and offset"], + ["T12:34:56.987654321+00:00[!+01:00]", "numeric, with T, !, and offset"], + ["1970-01-01T12:34:56.987654321[Africa/Lagos]", "named, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!America/Vancouver]", "named, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321[+00:00]", "numeric, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!-02:30]", "numeric, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321+00:00[Europe/London]", "named, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!Asia/Seoul]", "named, with date, offset, and !"], + ["1970-01-01T12:34:56.987654321+00:00[+01:00]", "numeric, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!-08:00]", "numeric, with date, offset, and !"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.from(arg); + + TemporalHelpers.assertPlainTime( + result, + 12, 34, 56, 987, 654, 321, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js new file mode 100644 index 0000000000..782b168939 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-trailing-junk.js @@ -0,0 +1,14 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: RangeError thrown if a string argument has trailing junk +features: [Temporal, arrow-function] +---*/ + +const arg = "15:23:30.100junk"; +assert.throws(RangeError, () => Temporal.PlainTime.from(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..7af06b9583 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-unknown-annotation.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Various forms of unknown annotation +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[foo=bar]", "alone"], + ["12:34:56.987654321[UTC][foo=bar]", "with time zone"], + ["12:34:56.987654321[u-ca=iso8601][foo=bar]", "with calendar"], + ["12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["T12:34:56.987654321[foo=bar]", "with T"], + ["T12:34:56.987654321[UTC][foo=bar]", "with T and time zone"], + ["T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with T and calendar"], + ["T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with T, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar]", "with date"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with date and calendar"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with date, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +tests.forEach(([arg, description]) => { + const result = Temporal.PlainTime.from(arg); + + TemporalHelpers.assertPlainTime( + result, + 12, 34, 56, 987, 654, 321, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js new file mode 100644 index 0000000000..865af83c0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = Temporal.PlainTime.from(arg); + TemporalHelpers.assertPlainTime(result, 0, 30, 0, 0, 0, 0, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..7a8e7ad7e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string-with-utc-designator.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", + "09:00:00Z[UTC]", + "09:00:00Z", +]; +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js new file mode 100644 index 0000000000..b96d370c32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-string.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Various ISO strings supported +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const tests = [ + ["15:23", 15, 23, 0, 0, 0, 0], + ["15:23:30", 15, 23, 30, 0, 0, 0], + ["15:23:30.123", 15, 23, 30, 123, 0, 0], + ["15:23:30.123456", 15, 23, 30, 123, 456, 0], + ["15:23:30.123456789", 15, 23, 30, 123, 456, 789], + ["1976-11-18T15:23:30.1", 15, 23, 30, 100, 0, 0], + ["1976-11-18T15:23:30.12", 15, 23, 30, 120, 0, 0], + ["1976-11-18T15:23:30.123", 15, 23, 30, 123, 0, 0], + ["1976-11-18T15:23:30.1234", 15, 23, 30, 123, 400, 0], + ["1976-11-18T15:23:30.12345", 15, 23, 30, 123, 450, 0], + ["1976-11-18T15:23:30.123456", 15, 23, 30, 123, 456, 0], + ["1976-11-18T15:23:30.1234567", 15, 23, 30, 123, 456, 700], + ["1976-11-18T15:23:30.12345678", 15, 23, 30, 123, 456, 780], + ["1976-11-18T15:23:30.123456789", 15, 23, 30, 123, 456, 789], + ["1976-11-18T15:23:30,12", 15, 23, 30, 120, 0, 0], + ["1976-11-18T15:23:30.12\u221202:00", 15, 23, 30, 120, 0, 0], + ["152330", 15, 23, 30, 0, 0, 0], + ["152330.1", 15, 23, 30, 100, 0, 0], + ["152330-08", 15, 23, 30, 0, 0, 0], + ["152330.1-08", 15, 23, 30, 100, 0, 0], + ["152330-0800", 15, 23, 30, 0, 0, 0], + ["152330.1-0800", 15, 23, 30, 100, 0, 0], + ["1976-11-18T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["19761118T15:23:30.1+00:00", 15, 23, 30, 100, 0, 0], + ["1976-11-18T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["1976-11-18T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["19761118T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["19761118T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["19761118T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["+0019761118T15:23:30.1+00:00", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["+001976-11-18T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["+0019761118T15:23:30.1+0000", 15, 23, 30, 100, 0, 0], + ["+0019761118T152330.1+00:00", 15, 23, 30, 100, 0, 0], + ["+0019761118T152330.1+0000", 15, 23, 30, 100, 0, 0], + ["15", 15, 0, 0, 0, 0, 0], + ["T15:23:30", 15, 23, 30, 0, 0, 0], + ["t152330", 15, 23, 30, 0, 0, 0], +]; + +for (const [input, ...expected] of tests) { + const result = Temporal.PlainTime.from(input); + assert.sameValue(expected.length, 6, input); + TemporalHelpers.assertPlainTime(result, ...expected, input); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-wrong-type.js new file mode 100644 index 0000000000..4a3b01707d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-wrong-type.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainTime +features: [BigInt, Symbol, Temporal] +---*/ + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => Temporal.PlainTime.from(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainTime, "Temporal.PlainTime, object"], + [Temporal.PlainTime.prototype, "Temporal.PlainTime.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => Temporal.PlainTime.from(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 0000000000..12356ae9e9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.from step 4: + 4. Return ? ToTemporalTime(_temporalTime_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = TemporalHelpers.specificOffsetTimeZone(-2); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const time = Temporal.PlainTime.from(datetime); + +TemporalHelpers.assertPlainTime(time, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 0000000000..e442577be0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const result = Temporal.PlainTime.from(datetime); +TemporalHelpers.assertPlainTime(result, 16, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..3cc1f97e08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..c5cfaeb4b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach(notCallable => { + const timeZone = new Temporal.TimeZone("UTC"); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => Temporal.PlainTime.from(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..f9d35b416f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_001, 86400_000_000_001, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..86c7e90fd6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => Temporal.PlainTime.from(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js new file mode 100644 index 0000000000..05d60e28ff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/builtin.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Tests that Temporal.PlainTime.from meets the requirements for built-in objects +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.from), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.from), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.from), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.from.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..a605d6c2d3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.from +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const base = { hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 }; + +[Infinity, -Infinity].forEach((inf) => { + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => Temporal.PlainTime.from({ ...base, [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => Temporal.PlainTime.from({ ...base, [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/leap-second.js new file mode 100644 index 0000000000..22694cb864 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/leap-second.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Leap second is a valid ISO string for PlainTime +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let arg = "2016-12-31T23:59:60"; + +const result1 = Temporal.PlainTime.from(arg); +TemporalHelpers.assertPlainTime( + result1, + 23, 59, 59, 0, 0, 0, + "leap second is a valid ISO string for PlainTime" +); + +const result2 = Temporal.PlainTime.from(arg, { overflow: "reject" }); +TemporalHelpers.assertPlainTime( + result2, + 23, 59, 59, 0, 0, 0, + "leap second is a valid ISO string for PlainTime" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; + +const result3 = Temporal.PlainTime.from(arg); +TemporalHelpers.assertPlainTime( + result3, + 23, 59, 59, 0, 0, 0, + "second: 60 is ignored in property bag for PlainTime" +); + +assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg, { overflow: "reject" }), + "second: 60 is rejected in property bag for PlainTime with overflow: reject" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js new file mode 100644 index 0000000000..cae3856a6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.from, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js new file mode 100644 index 0000000000..ecd305e0a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from.name is "from" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.from, "name", { + value: "from", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js new file mode 100644 index 0000000000..c93e2cfba9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/not-a-constructor.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Temporal.PlainTime.from does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.from(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.from), false, + "isConstructor(Temporal.PlainTime.from)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js new file mode 100644 index 0000000000..54a4045b5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/observable-get-overflow-argument-string-invalid.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: overflow property is extracted with ISO-invalid string argument. +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.PlainTime.from("24:60", object)); +assert.compareArray(actual, expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js new file mode 100644 index 0000000000..270bd8e3cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-invalid.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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 a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; + +for (const badOptions of values) { + assert.throws(TypeError, () => Temporal.PlainTime.from({ hours: 12 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-object.js new file mode 100644 index 0000000000..66d716cc23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-object.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.from +description: Empty object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainTime( + Temporal.PlainTime.from({ hour: 12, minute: 34 }, {}), 12, 34, 0, 0, 0, 0, + "options may be an empty plain object" +); + +TemporalHelpers.assertPlainTime( + Temporal.PlainTime.from({ hour: 12, minute: 34 }, () => {}), 12, 34, 0, 0, 0, 0, + "options may be an empty function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js new file mode 100644 index 0000000000..f9c0f77f64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const fields = { hour: 12, minute: 60 }; + +const explicit = Temporal.PlainTime.from(fields, undefined); +assert.sameValue(explicit.minute, 59, "default overflow is constrain"); + +const implicit = Temporal.PlainTime.from(fields); +assert.sameValue(implicit.minute, 59, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-wrong-type.js new file mode 100644 index 0000000000..ae4cb12dd2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/options-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js new file mode 100644 index 0000000000..e523323801 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/order-of-operations.js @@ -0,0 +1,55 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Properties on an object passed to from() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", + // ToTemporalTimeRecord + "get fields.hour", + "get fields.hour.valueOf", + "call fields.hour.valueOf", + "get fields.microsecond", + "get fields.microsecond.valueOf", + "call fields.microsecond.valueOf", + "get fields.millisecond", + "get fields.millisecond.valueOf", + "call fields.millisecond.valueOf", + "get fields.minute", + "get fields.minute.valueOf", + "call fields.minute.valueOf", + "get fields.nanosecond", + "get fields.nanosecond.valueOf", + "call fields.nanosecond.valueOf", + "get fields.second", + "get fields.second.valueOf", + "call fields.second.valueOf", +]; +const actual = []; + +const fields = TemporalHelpers.propertyBagObserver(actual, { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, + calendar: "iso8601", +}, "fields"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + overflow: "constrain", +}, "options"); + +const result = Temporal.PlainTime.from(fields, options); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js new file mode 100644 index 0000000000..5a306b7296 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-constrain.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: constrain value for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 26 }, { overflow: "constrain" }), + 23, 0, 0, 0, 0, 0); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 22 }, { overflow: "constrain" }), + 22, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js new file mode 100644 index 0000000000..dc3a9672ec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-invalid-string.js @@ -0,0 +1,35 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + { hour: 12 }, + "12:00", +]; + +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}")` + ); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js new file mode 100644 index 0000000000..9c2d998dc2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-reject.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: reject value for overflow option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => Temporal.PlainTime.from({ hour: 26 }, { overflow: "reject" })); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from({ hour: 22 }, { overflow: "reject" }), + 22, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js new file mode 100644 index 0000000000..8fb5547388 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-undefined.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + "12:00", +]; +validValues.forEach((value) => { + const explicit = Temporal.PlainTime.from(value, { overflow: undefined }); + TemporalHelpers.assertPlainTime(explicit, 12, 0, 0, 0, 0, 0, "overflow is ignored"); + const implicit = Temporal.PlainTime.from(value, {}); + TemporalHelpers.assertPlainTime(implicit, 12, 0, 0, 0, 0, 0, "overflow is ignored"); + const lambda = Temporal.PlainTime.from(value, () => {}); + TemporalHelpers.assertPlainTime(lambda, 12, 0, 0, 0, 0, 0, "overflow is ignored"); +}); + +const propertyBag = { hour: 26 }; +const explicit = Temporal.PlainTime.from(propertyBag, { overflow: undefined }); +TemporalHelpers.assertPlainTime(explicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = Temporal.PlainTime.from(propertyBag, {}); +TemporalHelpers.assertPlainTime(implicit, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); +const lambda = Temporal.PlainTime.from(propertyBag, () => {}); +TemporalHelpers.assertPlainTime(lambda, 23, 0, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js new file mode 100644 index 0000000000..ef10d18d2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/overflow-wrong-type.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.from step 2: + 2. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const validValues = [ + new Temporal.PlainTime(12), + { hour: 12 }, + "12:00", +]; +validValues.forEach((value) => TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => Temporal.PlainTime.from(value, { overflow }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 0, 0, 0, 0, 0, descr), +)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js new file mode 100644 index 0000000000..efe7b95c3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/plaintime-propertybag-no-time-units.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const props = {}; +assert.throws(TypeError, () => Temporal.PlainTime.from(props), "TypeError if at least one property is not present"); + +props.minute = 30; +const result = Temporal.PlainTime.from(props); +TemporalHelpers.assertPlainTime(result, 0, 30, 0, 0, 0, 0, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js new file mode 100644 index 0000000000..171870e39c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: The "from" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.from, + "function", + "`typeof PlainTime.from` is `function`" +); + +verifyProperty(Temporal.PlainTime, "from", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js new file mode 100644 index 0000000000..db63caf97f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/subclassing-ignored.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.from +description: The receiver is never called when calling from() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnoredStatic( + Temporal.PlainTime, + "from", + ["12:34:56.987654321"], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 321), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js new file mode 100644 index 0000000000..b42a38694c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/from/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00", + "-000000-12-07T03:24:30+00:00[UTC]", +]; + +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => Temporal.PlainTime.from(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js new file mode 100644 index 0000000000..db5a1f48e4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/hour-undefined.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Hour argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const explicit = new Temporal.PlainTime(undefined); +TemporalHelpers.assertPlainTime(explicit, 0, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(); +TemporalHelpers.assertPlainTime(implicit, 0, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..ba30e558fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/infinity-throws-rangeerror.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime throws a RangeError if any value is Infinity +esid: sec-temporal.plaintime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainTime(Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, 0, Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite hour", + [O(Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf"] + ], + [ + "infinite minute", + [O(1, "hour"), O(Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf"] + ], + [ + "infinite second", + [O(1, "hour"), O(1, "minute"), O(Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf"] + ], + [ + "infinite millisecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf"] + ], + [ + "infinite microsecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(Infinity, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf"] + ], + [ + "infinite nanosecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(Infinity, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf", "get nanosecond.valueOf", "call nanosecond.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js new file mode 100644 index 0000000000..50e2cd496b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js new file mode 100644 index 0000000000..076adb01ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/microsecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Microsecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56, 123]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js new file mode 100644 index 0000000000..cd32d9895b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/millisecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Millisecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js new file mode 100644 index 0000000000..877d433cea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/minute-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Minute argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const hour = 12; + +const explicit = new Temporal.PlainTime(hour, undefined); +TemporalHelpers.assertPlainTime(explicit, hour, 0, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(hour); +TemporalHelpers.assertPlainTime(implicit, hour, 0, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js new file mode 100644 index 0000000000..766cffff6c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Temporal.PlainTime.name is "PlainTime" +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime, "name", { + value: "PlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js new file mode 100644 index 0000000000..726f0efe4c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/nanosecond-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Nanosecond argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34, 56, 123, 456]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..a3ca04739f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-infinity-throws-rangeerror.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainDate throws a RangeError if any value is -Infinity +esid: sec-temporal.plaintime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +assert.throws(RangeError, () => new Temporal.PlainTime(-Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, -Infinity)); +assert.throws(RangeError, () => new Temporal.PlainTime(0, 0, 0, 0, 0, -Infinity)); + +const O = (primitiveValue, propertyName) => (calls) => TemporalHelpers.toPrimitiveObserver(calls, primitiveValue, propertyName); +const tests = [ + [ + "infinite hour", + [O(-Infinity, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf"] + ], + [ + "infinite minute", + [O(1, "hour"), O(-Infinity, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf"] + ], + [ + "infinite second", + [O(1, "hour"), O(1, "minute"), O(-Infinity, "second"), O(1, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf"] + ], + [ + "infinite millisecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(-Infinity, "millisecond"), O(1, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf"] + ], + [ + "infinite microsecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(-Infinity, "microsecond"), O(1, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf"] + ], + [ + "infinite nanosecond", + [O(1, "hour"), O(1, "minute"), O(1, "second"), O(1, "millisecond"), O(1, "microsecond"), O(-Infinity, "nanosecond")], + ["get hour.valueOf", "call hour.valueOf", "get minute.valueOf", "call minute.valueOf", "get second.valueOf", "call second.valueOf", "get millisecond.valueOf", "call millisecond.valueOf", "get microsecond.valueOf", "call microsecond.valueOf", "get nanosecond.valueOf", "call nanosecond.valueOf"] + ], +]; + +for (const [description, args, expected] of tests) { + const actual = []; + const args_ = args.map((o) => o(actual)); + assert.throws(RangeError, () => new Temporal.PlainTime(...args_), description); + assert.compareArray(actual, expected, `${description} order of operations`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js new file mode 100644 index 0000000000..acb69c0b37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/negative-zero.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Negative zero arguments are treated as zero. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(-0, -0, -0, -0, -0, -0); +TemporalHelpers.assertPlainTime(plainTime, 0, 0, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js new file mode 100644 index 0000000000..811fd97303 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: The "PlainTime" property of Temporal +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime, + "function", + "`typeof PlainTime` is `function`" +); + +verifyProperty(Temporal, "PlainTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-max.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-max.js new file mode 100644 index 0000000000..bbaded9b35 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-max.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Maximum allowed duration +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const maxCases = [ + ["P4294967295Y104249991374DT7H36M31.999999999S", "string with max years"], + [{ years: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max years"], + ["P4294967295M104249991374DT7H36M31.999999999S", "string with max weeks"], + [{ months: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max months"], + ["P4294967295W104249991374DT7H36M31.999999999S", "string with max weeks"], + [{ weeks: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max weeks"], + ["P104249991374DT7H36M31.999999999S", "string with max days"], + [{ days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max days"], + ["PT2501999792983H36M31.999999999S", "string with max hours"], + [{ hours: 2501999792983, nanoseconds: 2191999999999 }, "property bag with max hours"], + ["PT150119987579016M31.999999999S", "string with max minutes"], + [{ minutes: 150119987579016, nanoseconds: 31999999999 }, "property bag with max minutes"], + ["PT9007199254740991.999999999S", "string with max seconds"], + [{ seconds: 9007199254740991, nanoseconds: 999999999 }, "property bag with max seconds"], +]; + +for (const [arg, descr] of maxCases) { + const result = instance.add(arg); + TemporalHelpers.assertPlainTime(result, 7, 36, 31, 999, 999, 999, `operation succeeds with ${descr}`); +} + +const minCases = [ + ["-P4294967295Y104249991374DT7H36M31.999999999S", "string with min years"], + [{ years: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min years"], + ["-P4294967295M104249991374DT7H36M31.999999999S", "string with min months"], + [{ months: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min months"], + ["-P4294967295W104249991374DT7H36M31.999999999S", "string with min weeks"], + [{ weeks: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min weeks"], + ["-P104249991374DT7H36M31.999999999S", "string with min days"], + [{ days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min days"], + ["-PT2501999792983H36M31.999999999S", "string with min hours"], + [{ hours: -2501999792983, nanoseconds: -2191999999999 }, "property bag with min hours"], + ["-PT150119987579016M31.999999999S", "string with min minutes"], + [{ minutes: -150119987579016, nanoseconds: -31999999999 }, "property bag with min minutes"], + ["-PT9007199254740991.999999999S", "string with min seconds"], + [{ seconds: -9007199254740991, nanoseconds: -999999999 }, "property bag with min seconds"], +]; + +for (const [arg, descr] of minCases) { + const result = instance.add(arg); + TemporalHelpers.assertPlainTime(result, 16, 23, 28, 0, 0, 1, `operation succeeds with ${descr}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-out-of-range.js new file mode 100644 index 0000000000..7639ffc6f4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-out-of-range.js @@ -0,0 +1,75 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Duration-like argument that is out of range +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const cases = [ + // 2^32 = 4294967296 + ["P4294967296Y", "string with years > max"], + [{ years: 4294967296 }, "property bag with years > max"], + ["-P4294967296Y", "string with years < min"], + [{ years: -4294967296 }, "property bag with years < min"], + ["P4294967296M", "string with months > max"], + [{ months: 4294967296 }, "property bag with months > max"], + ["-P4294967296M", "string with months < min"], + [{ months: -4294967296 }, "property bag with months < min"], + ["P4294967296W", "string with weeks > max"], + [{ weeks: 4294967296 }, "property bag with weeks > max"], + ["-P4294967296W", "string with weeks < min"], + [{ weeks: -4294967296 }, "property bag with weeks < min"], + + // ceil(max safe integer / 86400) = 104249991375 + ["P104249991375D", "string with days > max"], + [{ days: 104249991375 }, "property bag with days > max"], + ["P104249991374DT24H", "string where hours balance into days > max"], + [{ days: 104249991374, hours: 24 }, "property bag where hours balance into days > max"], + ["-P104249991375D", "string with days < min"], + [{ days: -104249991375 }, "property bag with days < min"], + ["-P104249991374DT24H", "string where hours balance into days < min"], + [{ days: -104249991374, hours: -24 }, "property bag where hours balance into days < min"], + + // ceil(max safe integer / 3600) = 2501999792984 + ["PT2501999792984H", "string with hours > max"], + [{ hours: 2501999792984 }, "property bag with hours > max"], + ["PT2501999792983H60M", "string where minutes balance into hours > max"], + [{ hours: 2501999792983, minutes: 60 }, "property bag where minutes balance into hours > max"], + ["-PT2501999792984H", "string with hours < min"], + [{ hours: -2501999792984 }, "property bag with hours < min"], + ["-PT2501999792983H60M", "string where minutes balance into hours < min"], + [{ hours: -2501999792983, minutes: -60 }, "property bag where minutes balance into hours < min"], + + // ceil(max safe integer / 60) = 150119987579017 + ["PT150119987579017M", "string with minutes > max"], + [{ minutes: 150119987579017 }, "property bag with minutes > max"], + ["PT150119987579016M60S", "string where seconds balance into minutes > max"], + [{ minutes: 150119987579016, seconds: 60 }, "property bag where seconds balance into minutes > max"], + ["-PT150119987579017M", "string with minutes < min"], + [{ minutes: -150119987579017 }, "property bag with minutes < min"], + ["-PT150119987579016M60S", "string where seconds balance into minutes < min"], + [{ minutes: -150119987579016, seconds: -60 }, "property bag where seconds balance into minutes < min"], + + // 2^53 = 9007199254740992 + ["PT9007199254740992S", "string with seconds > max"], + [{ seconds: 9007199254740992 }, "property bag with seconds > max"], + [{ seconds: 9007199254740991, milliseconds: 1000 }, "property bag where milliseconds balance into seconds > max"], + [{ seconds: 9007199254740991, microseconds: 1000000 }, "property bag where microseconds balance into seconds > max"], + [{ seconds: 9007199254740991, nanoseconds: 1000000000 }, "property bag where nanoseconds balance into seconds > max"], + ["-PT9007199254740992S", "string with seconds < min"], + [{ seconds: -9007199254740992 }, "property bag with seconds < min"], + [{ seconds: -9007199254740991, milliseconds: -1000 }, "property bag where milliseconds balance into seconds < min"], + [{ seconds: -9007199254740991, microseconds: -1000000 }, "property bag where microseconds balance into seconds < min"], + [{ seconds: -9007199254740991, nanoseconds: -1000000000 }, "property bag where nanoseconds balance into seconds < min"], +]; + +for (const [arg, descr] of cases) { + assert.throws(RangeError, () => instance.add(arg), `${descr} is out of range`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-precision-exact-numerical-values.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-precision-exact-numerical-values.js new file mode 100644 index 0000000000..571afaef87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration-precision-exact-numerical-values.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Duration-like argument performs the range check with minimal floating point + precision loss +features: [Temporal] +---*/ + +// Based on a test case by André Bargull + +const instance = new Temporal.PlainTime(); + +const cases = [ + [ + { + milliseconds: 4503599627370497_000, // ℝ(𝔽(4503599627370497000)) = 4503599627370497024 + microseconds: 4503599627370495_000000, // ℝ(𝔽(4503599627370495000000)) = 4503599627370494951424 + }, + // 4503599627370497024 / 1000 + 4503599627370494951424 / 1000000 is + // 9007199254740991.975424, which is below the limit of 2**53 + "case where floating point inaccuracy brings total below limit, positive" + ], + [ + { + milliseconds: -4503599627370497_000, + microseconds: -4503599627370495_000000, + }, + "case where floating point inaccuracy brings total below limit, negative" + ], +]; + +for (const [arg, descr] of cases) { + instance.add(arg); // should not throw +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js new file mode 100644 index 0000000000..961d154bbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-duration.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.add +description: Duration arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const duration = Temporal.Duration.from("PT16H"); +TemporalHelpers.assertPlainTime(plainTime.add(duration), + 7, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js new file mode 100644 index 0000000000..54462bcdca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-higher-units.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Higher units are ignored. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const values = [ + new Temporal.Duration(0, 0, 0, 1), + new Temporal.Duration(0, 0, 1), + new Temporal.Duration(0, 1), + new Temporal.Duration(1), + { days: 1 }, + { weeks: 1 }, + { months: 1 }, + { years: 1 }, + "P1D", + "P1W", + "P1M", + "P1Y", +]; +for (const value of values) { + TemporalHelpers.assertPlainTime(plainTime.add(value), + 15, 23, 30, 123, 456, 789); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-invalid-property.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-invalid-property.js new file mode 100644 index 0000000000..c3c89846a1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-invalid-property.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: temporalDurationLike object must contain at least one correctly spelled property +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +assert.throws( + TypeError, + () => instance.add({}), + "Throws TypeError if no property is present" +); + +assert.throws( + TypeError, + () => instance.add({ nonsense: true }), + "Throws TypeError if no recognized property is present" +); + +assert.throws( + TypeError, + () => instance.add({ sign: 1 }), + "Sign property is not recognized" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-mixed-sign.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-mixed-sign.js new file mode 100644 index 0000000000..b95c4a0269 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-mixed-sign.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +assert.throws( + RangeError, + () => instance.add({ hours: 1, minutes: -30 }), + `mixed positive and negative values always throw` +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js new file mode 100644 index 0000000000..76496e794e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-not-object.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Passing a primitive other than string to add() throws +features: [Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +assert.throws(TypeError, () => instance.add(undefined), "undefined"); +assert.throws(TypeError, () => instance.add(null), "null"); +assert.throws(TypeError, () => instance.add(true), "boolean"); +assert.throws(RangeError, () => instance.add(""), "empty string"); +assert.throws(TypeError, () => instance.add(Symbol()), "Symbol"); +assert.throws(TypeError, () => instance.add(7), "number"); +assert.throws(TypeError, () => instance.add(7n), "bigint"); +assert.throws(TypeError, () => instance.add([]), "array"); +assert.throws(TypeError, () => instance.add(() => {}), "function"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js new file mode 100644 index 0000000000..665cf6f3b6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-object.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Plain object arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.add({ hours: 16 }), + 7, 23, 30, 123, 456, 789, "add 16 hours across midnight boundary"); +TemporalHelpers.assertPlainTime(plainTime.add({ minutes: 45 }), + 16, 8, 30, 123, 456, 789, "add 45 minutes"); +TemporalHelpers.assertPlainTime(plainTime.add({ seconds: 800 }), + 15, 36, 50, 123, 456, 789, "add 800 seconds"); +TemporalHelpers.assertPlainTime(plainTime.add({ milliseconds: 800 }), + 15, 23, 30, 923, 456, 789, "add 800 milliseconds"); +TemporalHelpers.assertPlainTime(plainTime.add({ microseconds: 800 }), + 15, 23, 30, 124, 256, 789, "add 800 microseconds"); +TemporalHelpers.assertPlainTime(plainTime.add({ nanoseconds: 300 }), + 15, 23, 30, 123, 457, 89, "add 300 nanoseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("07:23:30.123456789").add({ hours: -16 }), + 15, 23, 30, 123, 456, 789, "add -16 hours across midnight boundary"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("16:08:30.123456789").add({ minutes: -45 }), + 15, 23, 30, 123, 456, 789, "add -45 minutes"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:36:50.123456789").add({ seconds: -800 }), + 15, 23, 30, 123, 456, 789, "add -800 seconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.923456789").add({ milliseconds: -800 }), + 15, 23, 30, 123, 456, 789, "add -800 milliseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.124256789").add({ microseconds: -800 }), + 15, 23, 30, 123, 456, 789, "add -800 microseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.123457089").add({ nanoseconds: -300 }), + 15, 23, 30, 123, 456, 789, "add -300 nanoseconds"); +TemporalHelpers.assertPlainTime(plainTime.add({ minute: 1, hours: 1 }), + 16, 23, 30, 123, 456, 789, "misspelled property is ignored"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-singular-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-singular-properties.js new file mode 100644 index 0000000000..415dbad921 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-singular-properties.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Singular properties in the property bag are always ignored +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +[ + { 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, () => instance.add(badObject), + "Throw TypeError if temporalDurationLike is not valid"); +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-duration-too-large.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-duration-too-large.js new file mode 100644 index 0000000000..e155515611 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-duration-too-large.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + ParseTemporalDurationString throws a RangeError when the result is too large. +features: [Temporal] +---*/ + +// Number string too long to be representable as a Number value. +var ones = "1".repeat(1000); +assert.sameValue(Number(ones), Infinity); + +var time = new Temporal.PlainTime(); +var str = "PT" + ones + "S"; + +assert.throws(RangeError, () => time.add(str)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 0000000000..db31649d15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const midnight = new Temporal.PlainTime(); + +TemporalHelpers.assertPlainTime(midnight.add("PT1.03125H"), 1, 1, 52, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainTime(midnight.add("-PT1.03125H"), 22, 58, 7, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js new file mode 100644 index 0000000000..e604c8b210 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const resultHours = instance.add("-PT24.567890123H"); +TemporalHelpers.assertPlainTime(resultHours, 23, 25, 55, 595, 557, 200, "negative fractional hours"); + +const resultMinutes = instance.add("-PT1440.567890123M"); +TemporalHelpers.assertPlainTime(resultMinutes, 23, 59, 25, 926, 592, 620, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js new file mode 100644 index 0000000000..370e3af18c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.add("PT3M"); +TemporalHelpers.assertPlainTime(result, 12, 37, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js new file mode 100644 index 0000000000..ee6367ad1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/balance-negative-time-units.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal.plaintime.prototype.add step 4: + 4. Let _result_ be ? AddTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result1, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result3, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result4, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.add(new Temporal.Duration(0, 0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result5, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = time.add(new Temporal.Duration(0, 0, 0, 0, -2)); +TemporalHelpers.assertPlainTime(result6, 23, 1, 1, 1, 1, 1, "hours mod 24"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/branding.js new file mode 100644 index 0000000000..6d04681c4e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const add = Temporal.PlainTime.prototype.add; + +assert.sameValue(typeof add, "function"); + +const args = [new Temporal.Duration(0, 0, 0, 0, 5)]; + +assert.throws(TypeError, () => add.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => add.apply(null, args), "null"); +assert.throws(TypeError, () => add.apply(true, args), "true"); +assert.throws(TypeError, () => add.apply("", args), "empty string"); +assert.throws(TypeError, () => add.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => add.apply(1, args), "1"); +assert.throws(TypeError, () => add.apply({}, args), "plain object"); +assert.throws(TypeError, () => add.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => add.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js new file mode 100644 index 0000000000..3d3dc4cccd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Tests that Temporal.PlainTime.prototype.add + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.add), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.add), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.add), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.add.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..b6c769b42b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.add throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaintime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js new file mode 100644 index 0000000000..825d286d11 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Temporal.PlainTime.prototype.add.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.add, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js new file mode 100644 index 0000000000..053decb679 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Temporal.PlainTime.prototype.add.name is "add". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.add, "name", { + value: "add", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..2ec5d1f3f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.add throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaintime.prototype.add +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.add({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js new file mode 100644 index 0000000000..f9d007e9bc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.add({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.add({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js new file mode 100644 index 0000000000..e375de5ad7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Temporal.PlainTime.prototype.add does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.add(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.add), false, + "isConstructor(Temporal.PlainTime.prototype.add)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js new file mode 100644 index 0000000000..e8f2bcc5cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/options-ignored.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Options argument is ignored. +includes: [temporalHelpers.js] +features: [Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + "hello", + Symbol("foo"), + 1, + 1n, + {}, + () => {}, + { get overflow() { throw new Test262Error("should not get overflow") } }, +]; + +const time = Temporal.PlainTime.from("15:23:30.123456789"); +for (const options of values) { + TemporalHelpers.assertPlainTime(time.add({ hours: 1 }, options), + 16, 23, 30, 123, 456, 789); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js new file mode 100644 index 0000000000..ac4524dc17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/order-of-operations.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Properties on an object passed to add() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + "get fields.days", + "get fields.days.valueOf", + "call fields.days.valueOf", + "get fields.hours", + "get fields.hours.valueOf", + "call fields.hours.valueOf", + "get fields.microseconds", + "get fields.microseconds.valueOf", + "call fields.microseconds.valueOf", + "get fields.milliseconds", + "get fields.milliseconds.valueOf", + "call fields.milliseconds.valueOf", + "get fields.minutes", + "get fields.minutes.valueOf", + "call fields.minutes.valueOf", + "get fields.months", + "get fields.months.valueOf", + "call fields.months.valueOf", + "get fields.nanoseconds", + "get fields.nanoseconds.valueOf", + "call fields.nanoseconds.valueOf", + "get fields.seconds", + "get fields.seconds.valueOf", + "call fields.seconds.valueOf", + "get fields.weeks", + "get fields.weeks.valueOf", + "call fields.weeks.valueOf", + "get fields.years", + "get fields.years.valueOf", + "call fields.years.valueOf", +]; +const actual = []; +const fields = TemporalHelpers.propertyBagObserver(actual, { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}, "fields"); +const result = instance.add(fields); +TemporalHelpers.assertPlainTime(result, 13, 35, 57, 988, 655, 322); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-1.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-1.js new file mode 100644 index 0000000000..5c765a761b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-1.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Duration components are precise mathematical integers. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let duration = Temporal.Duration.from({ + microseconds: Number.MAX_SAFE_INTEGER, + nanoseconds: 1000, +}); + +let time = Temporal.PlainTime.from({ + microsecond: 1, +}); + +let result = time.add(duration); + +TemporalHelpers.assertPlainTime(result, 23, 47, 34, 740, 993, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-2.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-2.js new file mode 100644 index 0000000000..3bee5992cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-2.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: > + Duration components are precise mathematical integers. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let duration = Temporal.Duration.from({ + seconds: Number.MAX_SAFE_INTEGER, + nanoseconds: 999_999_999, +}); + +let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); + +let result = time.add(duration); + +TemporalHelpers.assertPlainTime(result, 7, 36, 31, 999, 999, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js new file mode 100644 index 0000000000..293e29f763 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: The "add" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.add, + "function", + "`typeof PlainTime.prototype.add` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "add", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js new file mode 100644 index 0000000000..2f88171099 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/add/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.add +description: Objects of a subclass are never created as return values for add() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "add", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 322), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/constructor.js new file mode 100644 index 0000000000..43a54d65c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/constructor.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.constructor +description: Test for Temporal.PlainTime.prototype.constructor. +info: The initial value of Temporal.PlainTime.prototype.constructor is %Temporal.PlainTime%. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype, "constructor", { + value: Temporal.PlainTime, + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js new file mode 100644 index 0000000000..114c98ea27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-cast.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: equals() casts its argument +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); + +assert.sameValue(t1.equals({ hour: 14, minute: 23, second: 30, millisecond: 123 }), false, "object"); +assert.sameValue(t1.equals({ hour: 8, minute: 44, second: 15, millisecond: 321 }), true, "object"); +assert.sameValue(t1.equals("14:23:30.123"), false, "string"); +assert.sameValue(t1.equals("08:44:15.321"), true, "string"); +assert.throws(TypeError, () => t1.equals({}), "no properties"); +assert.throws(TypeError, () => t1.equals({ hours: 8 }), "only plural property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-number.js new file mode 100644 index 0000000000..d2909de6f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: A number is invalid in place of an ISO string for Temporal.PlainTime +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + -123456.987654321, + 1234567, + 123456.9876543219, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.equals(arg), + `A number (${arg}) is not a valid ISO string for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..baf1fa2472 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-calendar-annotation.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[u-ca=iso8601]", "without time zone"], + ["12:34:56.987654321[UTC][u-ca=iso8601]", "with time zone"], + ["12:34:56.987654321[!u-ca=iso8601]", "with ! and no time zone"], + ["12:34:56.987654321[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["T12:34:56.987654321[u-ca=iso8601]", "with T and no time zone"], + ["T12:34:56.987654321[UTC][u-ca=iso8601]", "with T and time zone"], + ["T12:34:56.987654321[!u-ca=iso8601]", "with T, !, and no time zone"], + ["T12:34:56.987654321[UTC][!u-ca=iso8601]", "with T, !, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601]", "with date and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][u-ca=iso8601]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[!u-ca=iso8601]", "with !, date, and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][!u-ca=iso8601]", "with !, date, and time zone"], + ["12:34:56.987654321[u-ca=hebrew]", "calendar annotation ignored"], + ["12:34:56.987654321[u-ca=unknown]", "calendar annotation ignored even if unknown calendar"], + ["12:34:56.987654321[!u-ca=unknown]", "calendar annotation ignored even if unknown calendar with !"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.equals(arg); + + assert.sameValue( + result, + true, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..45706fa2c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-critical-unknown-annotation.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[!foo=bar]", + "T00:00[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..eacfcf8bda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-date-with-utc-offset.js @@ -0,0 +1,52 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const validStrings = [ + "12:34:56.987654321+00:00", + "12:34:56.987654321+00:00[UTC]", + "12:34:56.987654321+00:00[!UTC]", + "12:34:56.987654321-02:30[America/St_Johns]", + "1976-11-18T12:34:56.987654321+00:00", + "1976-11-18T12:34:56.987654321+00:00[UTC]", + "1976-11-18T12:34:56.987654321+00:00[!UTC]", + "1976-11-18T12:34:56.987654321-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.equals(arg); + + assert.sameValue( + result, + true, + `"${arg}" is a valid UTC offset with time for PlainTime` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.equals(arg), + `"${arg}" UTC offset without time is not valid for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..e4989f5525 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[u-ca=iso8601][!u-ca=iso8601]", + "00:00[!u-ca=iso8601][u-ca=iso8601]", + "00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..d3026d1fb9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-multiple-time-zone.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[UTC][UTC]", + "T00:00[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js new file mode 100644 index 0000000000..b918920ca4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.equals(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 0000000000..29548d9e14 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: ISO 8601 time designator "T" required in cases of ambiguity +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +TemporalHelpers.ISO.plainTimeStringsAmbiguous().forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.equals(arg), + `'${arg}' is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.equals(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.equals(arg), + `space is not accepted as a substitute for T prefix: '${arg}'` + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +TemporalHelpers.ISO.plainTimeStringsUnambiguous().forEach( + (arg) => instance.equals(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-separators.js new file mode 100644 index 0000000000..b7da0089c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-separators.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +const tests = [ + ["1976-11-18T12:34:56.987654321", "uppercase T"], + ["1976-11-18t12:34:56.987654321", "lowercase T"], + ["1976-11-18 12:34:56.987654321", "space between date and time"], + ["T12:34:56.987654321", "time-only uppercase T"], + ["t12:34:56.987654321", "time-only lowercase T"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.equals(arg); + + assert.sameValue( + result, + true, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..25e895d7f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-time-zone-annotation.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[Asia/Kolkata]", "named, with no offset"], + ["12:34:56.987654321[!Europe/Vienna]", "named, with ! and no offset"], + ["12:34:56.987654321[+00:00]", "numeric, with no offset"], + ["12:34:56.987654321[!-02:30]", "numeric, with ! and no offset"], + ["T12:34:56.987654321[UTC]", "named, with T and no offset"], + ["T12:34:56.987654321[!Africa/Abidjan]", "named, with T, !, and no offset"], + ["T12:34:56.987654321[+01:00]", "numeric, with T and no offset"], + ["T12:34:56.987654321[!-08:00]", "numeric, with T, !, and no offset"], + ["12:34:56.987654321+00:00[America/Sao_Paulo]", "named, with offset"], + ["12:34:56.987654321+00:00[!Asia/Tokyo]", "named, with ! and offset"], + ["12:34:56.987654321+00:00[-02:30]", "numeric, with offset"], + ["12:34:56.987654321+00:00[!+00:00]", "numeric, with ! and offset"], + ["T12:34:56.987654321+00:00[America/New_York]", "named, with T and offset"], + ["T12:34:56.987654321+00:00[!UTC]", "named, with T, !, and offset"], + ["T12:34:56.987654321+00:00[-08:00]", "numeric, with T and offset"], + ["T12:34:56.987654321+00:00[!+01:00]", "numeric, with T, !, and offset"], + ["1970-01-01T12:34:56.987654321[Africa/Lagos]", "named, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!America/Vancouver]", "named, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321[+00:00]", "numeric, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!-02:30]", "numeric, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321+00:00[Europe/London]", "named, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!Asia/Seoul]", "named, with date, offset, and !"], + ["1970-01-01T12:34:56.987654321+00:00[+01:00]", "numeric, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!-08:00]", "numeric, with date, offset, and !"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.equals(arg); + + assert.sameValue( + result, + true, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..62c6c39c71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-unknown-annotation.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +const tests = [ + ["12:34:56.987654321[foo=bar]", "alone"], + ["12:34:56.987654321[UTC][foo=bar]", "with time zone"], + ["12:34:56.987654321[u-ca=iso8601][foo=bar]", "with calendar"], + ["12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["T12:34:56.987654321[foo=bar]", "with T"], + ["T12:34:56.987654321[UTC][foo=bar]", "with T and time zone"], + ["T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with T and calendar"], + ["T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with T, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar]", "with date"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with date and calendar"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with date, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.equals(arg); + + assert.sameValue( + result, + true, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js new file mode 100644 index 0000000000..8177135fd5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-time-designator.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(0, 30, 0, 0, 0, 0); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.equals(arg); + assert.sameValue(result, true, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..1dd6f0ebb1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-string-with-utc-designator.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", + "09:00:00Z[UTC]", + "09:00:00Z", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js new file mode 100644 index 0000000000..dd4a481c5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainTime +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.equals(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainTime, "Temporal.PlainTime, object"], + [Temporal.PlainTime.prototype, "Temporal.PlainTime.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.equals(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 0000000000..7fdefea96b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,44 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = TemporalHelpers.specificOffsetTimeZone(-2); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +assert(new Temporal.PlainTime(1, 1, 1, 1, 0, 999).equals(datetime)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 0000000000..022a102f3e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(16, 50, 35, 0, 0, 1); +const result = instance.equals(datetime); +assert.sameValue(result, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..b59852bc69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..f6ab478702 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.equals(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..753983489c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..b7af51bb67 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.equals(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js new file mode 100644 index 0000000000..7f9a88ca8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Basic tests for equals() +features: [Temporal] +---*/ + +const t1 = Temporal.PlainTime.from("08:44:15.321"); +const t1bis = Temporal.PlainTime.from("08:44:15.321"); +const t2 = Temporal.PlainTime.from("14:23:30.123"); +assert.sameValue(t1.equals(t1), true, "same object"); +assert.sameValue(t1.equals(t1bis), true, "different object"); +assert.sameValue(t1.equals(t2), false, "different times"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/branding.js new file mode 100644 index 0000000000..130ebfd20f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const equals = Temporal.PlainTime.prototype.equals; + +assert.sameValue(typeof equals, "function"); + +const args = [new Temporal.PlainTime(12)]; + +assert.throws(TypeError, () => equals.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => equals.apply(null, args), "null"); +assert.throws(TypeError, () => equals.apply(true, args), "true"); +assert.throws(TypeError, () => equals.apply("", args), "empty string"); +assert.throws(TypeError, () => equals.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => equals.apply(1, args), "1"); +assert.throws(TypeError, () => equals.apply({}, args), "plain object"); +assert.throws(TypeError, () => equals.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => equals.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js new file mode 100644 index 0000000000..24538a40b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + Tests that Temporal.PlainTime.prototype.equals + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.equals), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.equals), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.equals), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.equals.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/leap-second.js new file mode 100644 index 0000000000..f2e3800021 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Leap second is a valid ISO string for PlainTime +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(23, 59, 59); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.equals(arg); +assert.sameValue( + result1, + true, + "leap second is a valid ISO string for PlainTime" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.equals(arg); +assert.sameValue( + result2, + true, + "second: 60 is ignored in property bag for PlainTime" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js new file mode 100644 index 0000000000..754520f733 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Temporal.PlainTime.prototype.equals.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.equals, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js new file mode 100644 index 0000000000..3861880ffb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Temporal.PlainTime.prototype.equals.name is "equals". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.equals, "name", { + value: "equals", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js new file mode 100644 index 0000000000..665cb307aa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: > + Temporal.PlainTime.prototype.equals does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.equals(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.equals), false, + "isConstructor(Temporal.PlainTime.prototype.equals)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js new file mode 100644 index 0000000000..46d372ec5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/plaintime-propertybag-no-time-units.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: Missing time units in property bag default to 0 +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(0, 30, 0, 0, 0, 0); + +const props = {}; +assert.throws(TypeError, () => instance.equals(props), "TypeError if no properties are present"); + +props.minute = 30; +const result = instance.equals(props); +assert.sameValue(result, true, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js new file mode 100644 index 0000000000..377b8bde6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.equals +description: The "equals" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.equals, + "function", + "`typeof PlainTime.prototype.equals` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "equals", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js new file mode 100644 index 0000000000..160eae9767 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/equals/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.equals +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00", + "-000000-12-07T03:24:30+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.equals(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/branding.js new file mode 100644 index 0000000000..d363874fc6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const getISOFields = Temporal.PlainTime.prototype.getISOFields; + +assert.sameValue(typeof getISOFields, "function"); + +assert.throws(TypeError, () => getISOFields.call(undefined), "undefined"); +assert.throws(TypeError, () => getISOFields.call(null), "null"); +assert.throws(TypeError, () => getISOFields.call(true), "true"); +assert.throws(TypeError, () => getISOFields.call(""), "empty string"); +assert.throws(TypeError, () => getISOFields.call(Symbol()), "symbol"); +assert.throws(TypeError, () => getISOFields.call(1), "1"); +assert.throws(TypeError, () => getISOFields.call({}), "plain object"); +assert.throws(TypeError, () => getISOFields.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => getISOFields.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js new file mode 100644 index 0000000000..d0535e6c9a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: > + Tests that Temporal.PlainTime.prototype.getISOFields + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.getISOFields), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.getISOFields), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.getISOFields), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.getISOFields.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js new file mode 100644 index 0000000000..efab816b91 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-names.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Correct field names on the object returned from getISOFields +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const result = time.getISOFields(); +assert.sameValue(result.isoHour, 12, "isoHour result"); +assert.sameValue(result.isoMinute, 34, "isoMinute result"); +assert.sameValue(result.isoSecond, 56, "isoSecond result"); +assert.sameValue(result.isoMillisecond, 987, "isoMillisecond result"); +assert.sameValue(result.isoMicrosecond, 654, "isoMicrosecond result"); +assert.sameValue(result.isoNanosecond, 321, "isoNanosecond result"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js new file mode 100644 index 0000000000..8c7f4fd3e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-prop-desc.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Properties on the returned object have the correct descriptor +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +const expected = [ + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoNanosecond", + "isoSecond", +]; + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const result = time.getISOFields(); + +for (const property of expected) { + verifyProperty(result, property, { + writable: true, + enumerable: true, + configurable: true, + }); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js new file mode 100644 index 0000000000..7c8e654af0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/field-traversal-order.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Properties added in correct order to object returned from getISOFields +includes: [compareArray.js] +features: [Temporal] +---*/ + +const expected = [ + "isoHour", + "isoMicrosecond", + "isoMillisecond", + "isoMinute", + "isoNanosecond", + "isoSecond", +]; + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const result = time.getISOFields(); + +assert.compareArray(Object.keys(result), expected); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js new file mode 100644 index 0000000000..2732f4a9df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Temporal.PlainTime.prototype.getISOFields.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.getISOFields, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js new file mode 100644 index 0000000000..a7c83c1466 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Temporal.PlainTime.prototype.getISOFields.name is "getISOFields". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.getISOFields, "name", { + value: "getISOFields", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js new file mode 100644 index 0000000000..057ed2c4fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: > + Temporal.PlainTime.prototype.getISOFields does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.getISOFields(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.getISOFields), false, + "isConstructor(Temporal.PlainTime.prototype.getISOFields)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js new file mode 100644 index 0000000000..c530cf5adb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: The "getISOFields" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.getISOFields, + "function", + "`typeof PlainTime.prototype.getISOFields` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "getISOFields", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prototype.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prototype.js new file mode 100644 index 0000000000..086916464a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/prototype.js @@ -0,0 +1,15 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.getisofields +description: Correct prototype on the object returned from getISOFields +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const result = instance.getISOFields(); +assert.sameValue(Object.getPrototypeOf(result), Object.prototype, "prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/getISOFields/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/branding.js new file mode 100644 index 0000000000..0329ac3688 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.hour +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const hour = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "hour").get; + +assert.sameValue(typeof hour, "function"); + +assert.throws(TypeError, () => hour.call(undefined), "undefined"); +assert.throws(TypeError, () => hour.call(null), "null"); +assert.throws(TypeError, () => hour.call(true), "true"); +assert.throws(TypeError, () => hour.call(""), "empty string"); +assert.throws(TypeError, () => hour.call(Symbol()), "symbol"); +assert.throws(TypeError, () => hour.call(1), "1"); +assert.throws(TypeError, () => hour.call({}), "plain object"); +assert.throws(TypeError, () => hour.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => hour.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js new file mode 100644 index 0000000000..2a54f27891 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.hour +description: The "hour" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "hour"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/hour/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/branding.js new file mode 100644 index 0000000000..412d16146a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.microsecond +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const microsecond = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "microsecond").get; + +assert.sameValue(typeof microsecond, "function"); + +assert.throws(TypeError, () => microsecond.call(undefined), "undefined"); +assert.throws(TypeError, () => microsecond.call(null), "null"); +assert.throws(TypeError, () => microsecond.call(true), "true"); +assert.throws(TypeError, () => microsecond.call(""), "empty string"); +assert.throws(TypeError, () => microsecond.call(Symbol()), "symbol"); +assert.throws(TypeError, () => microsecond.call(1), "1"); +assert.throws(TypeError, () => microsecond.call({}), "plain object"); +assert.throws(TypeError, () => microsecond.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => microsecond.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js new file mode 100644 index 0000000000..d05750e737 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.microsecond +description: The "microsecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "microsecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/microsecond/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/branding.js new file mode 100644 index 0000000000..18c94ea454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.millisecond +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const millisecond = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "millisecond").get; + +assert.sameValue(typeof millisecond, "function"); + +assert.throws(TypeError, () => millisecond.call(undefined), "undefined"); +assert.throws(TypeError, () => millisecond.call(null), "null"); +assert.throws(TypeError, () => millisecond.call(true), "true"); +assert.throws(TypeError, () => millisecond.call(""), "empty string"); +assert.throws(TypeError, () => millisecond.call(Symbol()), "symbol"); +assert.throws(TypeError, () => millisecond.call(1), "1"); +assert.throws(TypeError, () => millisecond.call({}), "plain object"); +assert.throws(TypeError, () => millisecond.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => millisecond.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js new file mode 100644 index 0000000000..cda2bc0bea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.millisecond +description: The "millisecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "millisecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/millisecond/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/branding.js new file mode 100644 index 0000000000..b981434142 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.minute +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const minute = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "minute").get; + +assert.sameValue(typeof minute, "function"); + +assert.throws(TypeError, () => minute.call(undefined), "undefined"); +assert.throws(TypeError, () => minute.call(null), "null"); +assert.throws(TypeError, () => minute.call(true), "true"); +assert.throws(TypeError, () => minute.call(""), "empty string"); +assert.throws(TypeError, () => minute.call(Symbol()), "symbol"); +assert.throws(TypeError, () => minute.call(1), "1"); +assert.throws(TypeError, () => minute.call({}), "plain object"); +assert.throws(TypeError, () => minute.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => minute.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js new file mode 100644 index 0000000000..c64a296a50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.minute +description: The "minute" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "minute"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/minute/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/branding.js new file mode 100644 index 0000000000..04da9afca7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.nanosecond +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const nanosecond = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "nanosecond").get; + +assert.sameValue(typeof nanosecond, "function"); + +assert.throws(TypeError, () => nanosecond.call(undefined), "undefined"); +assert.throws(TypeError, () => nanosecond.call(null), "null"); +assert.throws(TypeError, () => nanosecond.call(true), "true"); +assert.throws(TypeError, () => nanosecond.call(""), "empty string"); +assert.throws(TypeError, () => nanosecond.call(Symbol()), "symbol"); +assert.throws(TypeError, () => nanosecond.call(1), "1"); +assert.throws(TypeError, () => nanosecond.call({}), "plain object"); +assert.throws(TypeError, () => nanosecond.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => nanosecond.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js new file mode 100644 index 0000000000..9b47e79e69 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.nanosecond +description: The "nanosecond" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "nanosecond"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/nanosecond/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js new file mode 100644 index 0000000000..3e99b4fe25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/prop-desc.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal-plaintime-prototype +description: The "prototype" property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue(typeof Temporal.PlainTime.prototype, "object"); +assert.notSameValue(Temporal.PlainTime.prototype, null); + +verifyProperty(Temporal.PlainTime, "prototype", { + writable: false, + enumerable: false, + configurable: false, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/branding.js new file mode 100644 index 0000000000..97588eae2e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const round = Temporal.PlainTime.prototype.round; + +assert.sameValue(typeof round, "function"); + +const args = ["hour"]; + +assert.throws(TypeError, () => round.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => round.apply(null, args), "null"); +assert.throws(TypeError, () => round.apply(true, args), "true"); +assert.throws(TypeError, () => round.apply("", args), "empty string"); +assert.throws(TypeError, () => round.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => round.apply(1, args), "1"); +assert.throws(TypeError, () => round.apply({}, args), "plain object"); +assert.throws(TypeError, () => round.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => round.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js new file mode 100644 index 0000000000..ac46ab8fc4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: > + Tests that Temporal.PlainTime.prototype.round + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.round), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.round), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.round), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.round.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js new file mode 100644 index 0000000000..f4ff8fb86e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Temporal.PlainTime.prototype.round.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.round, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js new file mode 100644 index 0000000000..4f6f5b4c87 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Temporal.PlainTime.prototype.round.name is "round". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.round, "name", { + value: "round", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js new file mode 100644 index 0000000000..591cc2d3a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: > + Temporal.PlainTime.prototype.round does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.round(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.round), false, + "isConstructor(Temporal.PlainTime.prototype.round)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js new file mode 100644 index 0000000000..c576d9cebd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/options-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js new file mode 100644 index 0000000000..13c7270880 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: The "round" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.round, + "function", + "`typeof PlainTime.prototype.round` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "round", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js new file mode 100644 index 0000000000..294ba531ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/rounding-cross-midnight.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Rounding can cross midnight +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("23:59:59.999999999"); +for (const smallestUnit of ["hour", "minute", "second", "millisecond", "microsecond"]) { + TemporalHelpers.assertPlainTime(plainTime.round({ smallestUnit }), 0, 0, 0, 0, 0, 0); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js new file mode 100644 index 0000000000..ec7cbe2b56 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-hours.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 1 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 2 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 3 }), + 3, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 4 }), + 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 6 }), + 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js new file mode 100644 index 0000000000..46eab63aa7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-invalid.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("08:22:36.123456789"); + +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js new file mode 100644 index 0000000000..20d4a13ded --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-microseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 1 }), + 3, 34, 56, 987, 654, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 2 }), + 3, 34, 56, 987, 654, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 4 }), + 3, 34, 56, 987, 656, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 5 }), + 3, 34, 56, 987, 655, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 8 }), + 3, 34, 56, 987, 656, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 10 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 20 }), + 3, 34, 56, 987, 660, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 25 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 40 }), + 3, 34, 56, 987, 640, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 50 }), + 3, 34, 56, 987, 650, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 100 }), + 3, 34, 56, 987, 700, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 125 }), + 3, 34, 56, 987, 625, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 200 }), + 3, 34, 56, 987, 600, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 250 }), + 3, 34, 56, 987, 750, 0, "microseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microseconds", roundingIncrement: 500 }), + 3, 34, 56, 987, 500, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js new file mode 100644 index 0000000000..e84da703b2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-milliseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 1 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 2 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 4 }), + 3, 34, 56, 988, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 5 }), + 3, 34, 56, 990, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 8 }), + 3, 34, 56, 984, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 10 }), + 3, 34, 56, 990, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 20 }), + 3, 34, 56, 980, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 25 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 40 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 50 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 100 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 125 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 200 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 250 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "milliseconds", roundingIncrement: 500 }), + 3, 34, 57, 0, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js new file mode 100644 index 0000000000..88b8a73dd1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-minutes.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 1 }), + 3, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 2 }), + 3, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 3 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 4 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 5 }), + 3, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 6 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 10 }), + 3, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 12 }), + 3, 36, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 15 }), + 3, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 20 }), + 3, 40, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minutes", roundingIncrement: 30 }), + 3, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js new file mode 100644 index 0000000000..c1874a2bd7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nan.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws(RangeError, () => time.round({ smallestUnit: 'second', roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js new file mode 100644 index 0000000000..9b6a1c8f77 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-nanoseconds.js @@ -0,0 +1,60 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 3, 34, 56, 987, 654, 321, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 3, 34, 56, 987, 654, 322, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 3, 34, 56, 987, 654, 325, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 3, 34, 56, 987, 654, 320, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 3, 34, 56, 987, 654, 300, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 3, 34, 56, 987, 654, 300, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 3, 34, 56, 987, 654, 375, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 3, 34, 56, 987, 654, 400, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 3, 34, 56, 987, 654, 250, "nanoseconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 3, 34, 56, 987, 654, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js new file mode 100644 index 0000000000..e70e20ea85 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-non-integer.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Rounding for roundingIncrement option +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = time.round({ smallestUnit: "nanosecond", roundingIncrement: 2.5, roundingMode: "expand" }); +TemporalHelpers.assertPlainTime(result, 12, 34, 56, 0, 0, 6, "roundingIncrement 2.5 truncates to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js new file mode 100644 index 0000000000..832bae5f60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-out-of-range.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when roundingIncrement option out of range +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: -Infinity })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: -1 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: 0 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: 0.9 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: 1e9 + 1 })); +assert.throws(RangeError, () => time.round({ smallestUnit: "nanoseconds", roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js new file mode 100644 index 0000000000..342bccbf37 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-seconds.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(3, 34, 56, 987, 654, 321); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 1 }), + 3, 34, 57, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 2 }), + 3, 34, 56, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 3 }), + 3, 34, 57, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 4 }), + 3, 34, 56, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 5 }), + 3, 34, 55, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 6 }), + 3, 34, 54, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 10 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 12 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 15 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 20 }), + 3, 35, 0, 0, 0, 0, "seconds"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "seconds", roundingIncrement: 30 }), + 3, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js new file mode 100644 index 0000000000..a587e8c163 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const explicit = time.round({ smallestUnit: 'second', roundingIncrement: undefined }); +TemporalHelpers.assertPlainTime(explicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +const implicit = time.round({ smallestUnit: 'second' }); +TemporalHelpers.assertPlainTime(implicit, 12, 34, 57, 0, 0, 0, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js new file mode 100644 index 0000000000..fa9fbc8404 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingincrement-wrong-type.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.round step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => time.round({ smallestUnit: 'second', roundingIncrement }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 57, 0, 0, 0, descr), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js new file mode 100644 index 0000000000..022e5156f0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-ceil.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 47]], + ["second", [13, 46, 24]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 988]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "ceil"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-expand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-expand.js new file mode 100644 index 0000000000..2cfffad15d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-expand.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "expand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 47]], + ["second", [13, 46, 24]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 988]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "expand"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js new file mode 100644 index 0000000000..e8616991f2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-floor.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [13]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 123]], + ["microsecond", [13, 46, 23, 123, 987]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "floor"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfCeil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfCeil.js new file mode 100644 index 0000000000..d026326ec0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfCeil.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "halfCeil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 988]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "halfCeil"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfEven.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfEven.js new file mode 100644 index 0000000000..1b1896efe1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfEven.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "halfEven". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 988]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "halfEven"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js new file mode 100644 index 0000000000..c0f93790fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfExpand.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 988]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "halfExpand"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfFloor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfFloor.js new file mode 100644 index 0000000000..0bfe52baff --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfFloor.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "halfFloor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 987]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "halfFloor"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfTrunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfTrunc.js new file mode 100644 index 0000000000..bcab3dd219 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-halfTrunc.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "halfTrunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [14]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 124]], + ["microsecond", [13, 46, 23, 123, 987]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "halfTrunc"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js new file mode 100644 index 0000000000..619f34d9fb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => time.round({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js new file mode 100644 index 0000000000..a687834ecc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-trunc.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(13, 46, 23, 123, 987, 500); + +const expected = [ + ["hour", [13]], + ["minute", [13, 46]], + ["second", [13, 46, 23]], + ["millisecond", [13, 46, 23, 123]], + ["microsecond", [13, 46, 23, 123, 987]], + ["nanosecond", [13, 46, 23, 123, 987, 500]], +]; + +const roundingMode = "trunc"; + +expected.forEach(([smallestUnit, expected]) => { + const [h, min = 0, s = 0, ms = 0, µs = 0, ns = 0] = expected; + TemporalHelpers.assertPlainTime( + instance.round({ smallestUnit, roundingMode }), + h, min, s, ms, µs, ns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js new file mode 100644 index 0000000000..8f1d4d44a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-undefined.js @@ -0,0 +1,56 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Tests calculations with roundingMode undefined. +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const plainTime = Temporal.PlainTime.from("13:46:23.123456789"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour", roundingMode: undefined }), + 14, 0, 0, 0, 0, 0, "hour"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "hour" }), + 14, 0, 0, 0, 0, 0, "hour"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute", roundingMode: undefined }), + 13, 46, 0, 0, 0, 0, "minute"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "minute" }), + 13, 46, 0, 0, 0, 0, "minute"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second", roundingMode: undefined }), + 13, 46, 23, 0, 0, 0, "second"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "second" }), + 13, 46, 23, 0, 0, 0, "second"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond", roundingMode: undefined }), + 13, 46, 23, 123, 0, 0, "millisecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "millisecond" }), + 13, 46, 23, 123, 0, 0, "millisecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond", roundingMode: undefined }), + 13, 46, 23, 123, 457, 0, "microsecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "microsecond" }), + 13, 46, 23, 123, 457, 0, "microsecond"); + +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond", roundingMode: undefined }), + 13, 46, 23, 123, 456, 789, "nanosecond"); +TemporalHelpers.assertPlainTime( + plainTime.round({ smallestUnit: "nanosecond" }), + 13, 46, 23, 123, 456, 789, "nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js new file mode 100644 index 0000000000..3c8d77339d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "halfExpand", + (roundingMode) => time.round({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundto-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundto-invalid-string.js new file mode 100644 index 0000000000..90b17f979c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/roundto-invalid-string.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js new file mode 100644 index 0000000000..23e2b56612 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-invalid-string.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js new file mode 100644 index 0000000000..0a1df6022a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-missing.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: RangeError thrown when smallestUnit option is missing +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +assert.throws(TypeError, () => plainTime.round()); +assert.throws(RangeError, () => plainTime.round({})); +assert.throws(RangeError, () => plainTime.round({ roundingIncrement: 1, roundingMode: "ceil" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js new file mode 100644 index 0000000000..8cc10926f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.round({ smallestUnit }), validUnits); +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.round(smallestUnit), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js new file mode 100644 index 0000000000..e3cc87fa1b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-string-shorthand.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: String as first argument is equivalent to options bag with smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +validUnits.forEach((smallestUnit) => { + const full = instance.round({ smallestUnit }); + const shorthand = instance.round(smallestUnit); + TemporalHelpers.assertPlainTimesEqual(shorthand, full, `"${smallestUnit}" as first argument to round is equivalent to options bag`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js new file mode 100644 index 0000000000..ccaabccf26 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => time.round({ smallestUnit }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 123, 988, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js new file mode 100644 index 0000000000..0b574f0a9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/round/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.round +description: Objects of a subclass are never created as return values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "round", + [{ smallestUnit: 'second' }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 57, 0, 0, 0), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/branding.js new file mode 100644 index 0000000000..aa3af6a146 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.second +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const second = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "second").get; + +assert.sameValue(typeof second, "function"); + +assert.throws(TypeError, () => second.call(undefined), "undefined"); +assert.throws(TypeError, () => second.call(null), "null"); +assert.throws(TypeError, () => second.call(true), "true"); +assert.throws(TypeError, () => second.call(""), "empty string"); +assert.throws(TypeError, () => second.call(Symbol()), "symbol"); +assert.throws(TypeError, () => second.call(1), "1"); +assert.throws(TypeError, () => second.call({}), "plain object"); +assert.throws(TypeError, () => second.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => second.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js new file mode 100644 index 0000000000..c4a03e47c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/prop-desc.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.plaintime.prototype.second +description: The "second" property of Temporal.PlainTime.prototype +features: [Temporal] +---*/ + +const descriptor = Object.getOwnPropertyDescriptor(Temporal.PlainTime.prototype, "second"); +assert.sameValue(typeof descriptor.get, "function"); +assert.sameValue(descriptor.set, undefined); +assert.sameValue(descriptor.enumerable, false); +assert.sameValue(descriptor.configurable, true); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/second/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js new file mode 100644 index 0000000000..b53b7be74b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-cast.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Casts the argument +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertDuration(plainTime.since("16:34"), + 0, 0, 0, 0, /* hours = */ -1, /* minutes = */ -10, /* seconds = */ -29, -876, -543, -211, "string"); +TemporalHelpers.assertDuration(plainTime.since({ hour: 16, minute: 34 }), + 0, 0, 0, 0, /* hours = */ -1, /* minutes = */ -10, /* seconds = */ -29, -876, -543, -211, "object"); + +assert.throws(TypeError, () => plainTime.since({}), "empty"); +assert.throws(TypeError, () => plainTime.since({ minutes: 30 }), "only plural 'minutes'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-number.js new file mode 100644 index 0000000000..df9cd66d25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: A number is invalid in place of an ISO string for Temporal.PlainTime +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + -123456.987654321, + 1234567, + 123456.9876543219, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.since(arg), + `A number (${arg}) is not a valid ISO string for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..ece0c996a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-calendar-annotation.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[u-ca=iso8601]", "without time zone"], + ["12:34:56.987654321[UTC][u-ca=iso8601]", "with time zone"], + ["12:34:56.987654321[!u-ca=iso8601]", "with ! and no time zone"], + ["12:34:56.987654321[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["T12:34:56.987654321[u-ca=iso8601]", "with T and no time zone"], + ["T12:34:56.987654321[UTC][u-ca=iso8601]", "with T and time zone"], + ["T12:34:56.987654321[!u-ca=iso8601]", "with T, !, and no time zone"], + ["T12:34:56.987654321[UTC][!u-ca=iso8601]", "with T, !, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601]", "with date and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][u-ca=iso8601]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[!u-ca=iso8601]", "with !, date, and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][!u-ca=iso8601]", "with !, date, and time zone"], + ["12:34:56.987654321[u-ca=hebrew]", "calendar annotation ignored"], + ["12:34:56.987654321[u-ca=unknown]", "calendar annotation ignored even if unknown calendar"], + ["12:34:56.987654321[!u-ca=unknown]", "calendar annotation ignored even if unknown calendar with !"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.since(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..84eb98a585 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-critical-unknown-annotation.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[!foo=bar]", + "T00:00[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..83a2cb8f80 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-date-with-utc-offset.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const validStrings = [ + "12:34:56.987654321+00:00", + "12:34:56.987654321+00:00[UTC]", + "12:34:56.987654321+00:00[!UTC]", + "12:34:56.987654321-02:30[America/St_Johns]", + "1976-11-18T12:34:56.987654321+00:00", + "1976-11-18T12:34:56.987654321+00:00[UTC]", + "1976-11-18T12:34:56.987654321+00:00[!UTC]", + "1976-11-18T12:34:56.987654321-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.since(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `"${arg}" is a valid UTC offset with time for PlainTime` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.since(arg), + `"${arg}" UTC offset without time is not valid for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..02cb57b271 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[u-ca=iso8601][!u-ca=iso8601]", + "00:00[!u-ca=iso8601][u-ca=iso8601]", + "00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..6a50d1787f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-multiple-time-zone.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[UTC][UTC]", + "T00:00[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js new file mode 100644 index 0000000000..0f4f71046c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.since(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 0000000000..28da5edc0e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: ISO 8601 time designator "T" required in cases of ambiguity +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +TemporalHelpers.ISO.plainTimeStringsAmbiguous().forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.since(arg), + `'${arg}' is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.since(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.since(arg), + `space is not accepted as a substitute for T prefix: '${arg}'` + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +TemporalHelpers.ISO.plainTimeStringsUnambiguous().forEach( + (arg) => instance.since(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-separators.js new file mode 100644 index 0000000000..252d7a6e53 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-separators.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["1976-11-18T12:34:56.987654321", "uppercase T"], + ["1976-11-18t12:34:56.987654321", "lowercase T"], + ["1976-11-18 12:34:56.987654321", "space between date and time"], + ["T12:34:56.987654321", "time-only uppercase T"], + ["t12:34:56.987654321", "time-only lowercase T"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.since(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..3f75d12f81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-time-zone-annotation.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[Asia/Kolkata]", "named, with no offset"], + ["12:34:56.987654321[!Europe/Vienna]", "named, with ! and no offset"], + ["12:34:56.987654321[+00:00]", "numeric, with no offset"], + ["12:34:56.987654321[!-02:30]", "numeric, with ! and no offset"], + ["T12:34:56.987654321[UTC]", "named, with T and no offset"], + ["T12:34:56.987654321[!Africa/Abidjan]", "named, with T, !, and no offset"], + ["T12:34:56.987654321[+01:00]", "numeric, with T and no offset"], + ["T12:34:56.987654321[!-08:00]", "numeric, with T, !, and no offset"], + ["12:34:56.987654321+00:00[America/Sao_Paulo]", "named, with offset"], + ["12:34:56.987654321+00:00[!Asia/Tokyo]", "named, with ! and offset"], + ["12:34:56.987654321+00:00[-02:30]", "numeric, with offset"], + ["12:34:56.987654321+00:00[!+00:00]", "numeric, with ! and offset"], + ["T12:34:56.987654321+00:00[America/New_York]", "named, with T and offset"], + ["T12:34:56.987654321+00:00[!UTC]", "named, with T, !, and offset"], + ["T12:34:56.987654321+00:00[-08:00]", "numeric, with T and offset"], + ["T12:34:56.987654321+00:00[!+01:00]", "numeric, with T, !, and offset"], + ["1970-01-01T12:34:56.987654321[Africa/Lagos]", "named, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!America/Vancouver]", "named, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321[+00:00]", "numeric, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!-02:30]", "numeric, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321+00:00[Europe/London]", "named, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!Asia/Seoul]", "named, with date, offset, and !"], + ["1970-01-01T12:34:56.987654321+00:00[+01:00]", "numeric, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!-08:00]", "numeric, with date, offset, and !"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.since(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..1c610e5c72 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-unknown-annotation.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Various forms of unknown annotation +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[foo=bar]", "alone"], + ["12:34:56.987654321[UTC][foo=bar]", "with time zone"], + ["12:34:56.987654321[u-ca=iso8601][foo=bar]", "with calendar"], + ["12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["T12:34:56.987654321[foo=bar]", "with T"], + ["T12:34:56.987654321[UTC][foo=bar]", "with T and time zone"], + ["T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with T and calendar"], + ["T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with T, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar]", "with date"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with date and calendar"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with date, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.since(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js new file mode 100644 index 0000000000..6a1ac52bfb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.since(arg); + TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 30, 0, 0, 0, 1, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..c7325625ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-string-with-utc-designator.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", + "09:00:00Z[UTC]", + "09:00:00Z", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-wrong-type.js new file mode 100644 index 0000000000..7aaa3324f5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainTime +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.since(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainTime, "Temporal.PlainTime, object"], + [Temporal.PlainTime.prototype, "Temporal.PlainTime.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.since(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 0000000000..ad80b7ee57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = TemporalHelpers.specificOffsetTimeZone(-2); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainTime().since(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, -1, -1, -1, -1, 0, -999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 0000000000..5edc564f07 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(15); +const result = instance.since(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, -1, -50, -35, 0, 0, -1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..0b73484ed0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..a977d4f8c7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.since(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..1c5998e0bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..cec6b03fac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.since(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js new file mode 100644 index 0000000000..78b3f45f33 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/balance-negative-time-units.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaintime.prototype.since step 12: + 12. Let _result_ be ! DifferenceTime(_other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.since(new Temporal.PlainTime(0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.since(new Temporal.PlainTime(0, 0, 0, 0, 2)); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.since(new Temporal.PlainTime(0, 0, 0, 2)); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.since(new Temporal.PlainTime(0, 0, 2)); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.since(new Temporal.PlainTime(0, 2)); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = time.since(new Temporal.PlainTime(2)); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js new file mode 100644 index 0000000000..2c4a6da6ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Basic usage +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const one = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const two = new Temporal.PlainTime(14, 23, 30, 123, 456, 789); +const three = new Temporal.PlainTime(13, 30, 30, 123, 456, 789); + +TemporalHelpers.assertDuration(one.since(two), + 0, 0, 0, 0, /* hours = */ 1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(two.since(one), + 0, 0, 0, 0, /* hours = */ -1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(one.since(three), + 0, 0, 0, 0, /* hours = */ 1, 53, 0, 0, 0, 0); +TemporalHelpers.assertDuration(three.since(one), + 0, 0, 0, 0, /* hours = */ -1, -53, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/branding.js new file mode 100644 index 0000000000..58e28d48d8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const since = Temporal.PlainTime.prototype.since; + +assert.sameValue(typeof since, "function"); + +const args = [new Temporal.PlainTime(12)]; + +assert.throws(TypeError, () => since.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => since.apply(null, args), "null"); +assert.throws(TypeError, () => since.apply(true, args), "true"); +assert.throws(TypeError, () => since.apply("", args), "empty string"); +assert.throws(TypeError, () => since.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => since.apply(1, args), "1"); +assert.throws(TypeError, () => since.apply({}, args), "plain object"); +assert.throws(TypeError, () => since.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => since.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js new file mode 100644 index 0000000000..b1d7800d31 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + Tests that Temporal.PlainTime.prototype.since + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.since), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.since), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.since), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.since.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js new file mode 100644 index 0000000000..730fe43204 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-invalid-string.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when largestUnit option not one of the allowed string values +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 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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js new file mode 100644 index 0000000000..b216349ac0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => later.since(earlier, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js new file mode 100644 index 0000000000..340d757b34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when smallestUnit is larger than largestUnit +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 units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => later.since(earlier, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js new file mode 100644 index 0000000000..43b1b4a58b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +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 explicit = later.since(earlier, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js new file mode 100644 index 0000000000..f9ecd7f958 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "second", + (largestUnit) => later.since(earlier, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js new file mode 100644 index 0000000000..61a7c65efe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/largestunit.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: PlainTime.since with various largestUnit values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const fourFortyEight = new Temporal.PlainTime(4, 48, 55); +const elevenFiftyNine = new Temporal.PlainTime(11, 59, 58); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit unspecified)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'auto' }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is auto)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'hours' }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is hours)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'minutes' }), 0, 0, 0, 0, 0, 431, 3, 0, 0, 0, 'does not include higher units than necessary (largest unit is minutes)'); +TemporalHelpers.assertDuration(elevenFiftyNine.since(fourFortyEight, { largestUnit: 'seconds' }), 0, 0, 0, 0, 0, 0, 25863, 0, 0, 0, 'does not include higher units than necessary (largest unit is seconds)'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/leap-second.js new file mode 100644 index 0000000000..428352a5f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/leap-second.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Leap second is a valid ISO string for PlainTime +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(23, 59, 59); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.since(arg); +TemporalHelpers.assertDuration( + result1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "leap second is a valid ISO string for PlainTime" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.since(arg); +TemporalHelpers.assertDuration( + result2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "second: 60 is ignored in property bag for PlainTime" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js new file mode 100644 index 0000000000..1905d55029 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Temporal.PlainTime.prototype.since.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.since, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js new file mode 100644 index 0000000000..5ba97cebbb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Temporal.PlainTime.prototype.since.name is "since". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.since, "name", { + value: "since", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js new file mode 100644 index 0000000000..43b9cd80f9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: > + Temporal.PlainTime.prototype.since does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.since(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.since), false, + "isConstructor(Temporal.PlainTime.prototype.since)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js new file mode 100644 index 0000000000..da9c831983 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +const time = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const one = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); + +for (const badOptions of values) { + assert.throws(TypeError, () => time.since(one, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-object.js new file mode 100644 index 0000000000..1212676bd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-object.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const result1 = instance.since(new Temporal.PlainTime(12, 34, 56), {}); +TemporalHelpers.assertDuration( + result1, 0, 0, 0, 0, -12, -34, -56, 0, 0, 0, + "options may be an empty plain object" +); + +const result2 = instance.since(new Temporal.PlainTime(12, 34, 56), () => {}); +TemporalHelpers.assertDuration( + result2, 0, 0, 0, 0, -12, -34, -56, 0, 0, 0, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js new file mode 100644 index 0000000000..e31734100d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(18, 34, 56, 987, 654, 322); + +const explicit = later.since(earlier, undefined); +assert.sameValue(explicit.hours, 6, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = later.since(earlier); +assert.sameValue(implicit.hours, 6, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js new file mode 100644 index 0000000000..78e17fa2f8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/order-of-operations.js new file mode 100644 index 0000000000..33f3b9bac5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/order-of-operations.js @@ -0,0 +1,95 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Properties on an object passed to since() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + // ToTemporalTime + "get other.hour", + "get other.hour.valueOf", + "call other.hour.valueOf", + "get other.microsecond", + "get other.microsecond.valueOf", + "call other.microsecond.valueOf", + "get other.millisecond", + "get other.millisecond.valueOf", + "call other.millisecond.valueOf", + "get other.minute", + "get other.minute.valueOf", + "call other.minute.valueOf", + "get other.nanosecond", + "get other.nanosecond.valueOf", + "call other.nanosecond.valueOf", + "get other.second", + "get other.second.valueOf", + "call other.second.valueOf", + // CopyDataProperties + "ownKeys options", + "getOwnPropertyDescriptor options.roundingIncrement", + "get options.roundingIncrement", + "getOwnPropertyDescriptor options.roundingMode", + "get options.roundingMode", + "getOwnPropertyDescriptor options.largestUnit", + "get options.largestUnit", + "getOwnPropertyDescriptor options.smallestUnit", + "get options.smallestUnit", + "getOwnPropertyDescriptor options.additional", + "get options.additional", + // GetDifferenceSettings + "get options.largestUnit.toString", + "call options.largestUnit.toString", + "get options.roundingIncrement.valueOf", + "call options.roundingIncrement.valueOf", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", +]; +const actual = []; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const other = TemporalHelpers.propertyBagObserver(actual, { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, + calendar: "iso8601", +}, "other"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + roundingIncrement: 1, + roundingMode: "trunc", + largestUnit: "hours", + smallestUnit: "nanoseconds", + additional: true, +}, "options"); + +const result = instance.since(other, options); +assert.compareArray(actual, expected, "order of operations"); + +actual.splice(0); // clear + +// short-circuit does not skip reading options +const identicalPropertyBag = TemporalHelpers.propertyBagObserver(actual, { + hour: 12, + minute: 34, + second: 56, + millisecond: 987, + microsecond: 654, + nanosecond: 321, +}, "other"); +instance.since(identicalPropertyBag, options); +assert.compareArray(actual, expected, "order of operations with identical times"); + +actual.splice(0); // clear + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/plaintime-propertybag-no-time-units.js new file mode 100644 index 0000000000..563d9cd8b5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/plaintime-propertybag-no-time-units.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); + +const props = {}; +assert.throws(TypeError, () => instance.since(props), "TypeError if no properties are present"); + +props.minute = 30; +const result = instance.since(props); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 30, 0, 0, 0, 1, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js new file mode 100644 index 0000000000..1487fef147 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: The "since" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.since, + "function", + "`typeof PlainTime.prototype.since` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "since", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js new file mode 100644 index 0000000000..8821442df1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/result-sub-second.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Supports sub-second precision +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time1 = Temporal.PlainTime.from("10:23:15"); +const time2 = Temporal.PlainTime.from("17:15:57.250250250"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 24762250, 250, 250, "milliseconds"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 24762250250, 250, "microseconds"); + +TemporalHelpers.assertDuration(time2.since(time1, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 0, 24762250250250, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/round-cross-unit-boundary.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/round-cross-unit-boundary.js new file mode 100644 index 0000000000..7d6be19a63 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/round-cross-unit-boundary.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Rounding can cross unit boundaries up to largestUnit +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(); +const later = new Temporal.PlainTime(1, 59, 59); +const duration = earlier.since(later, { largestUnit: "hours", smallestUnit: "minutes", roundingMode: "expand" }); +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, "-1:60 balances to -2 hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js new file mode 100644 index 0000000000..1318ce0a71 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-hours.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 3 }), + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 4 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 6 }), + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js new file mode 100644 index 0000000000..e1a03301e1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-invalid.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js new file mode 100644 index 0000000000..1013fb750e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-microseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 196, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 195, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 192, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 190, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 180, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 175, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 160, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 150, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 100, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 125, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js new file mode 100644 index 0000000000..5a74a65fea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-milliseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 840, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 500, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js new file mode 100644 index 0000000000..e765503076 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-minutes.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 33, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 32, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 24, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 20, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js new file mode 100644 index 0000000000..62bfdb33d2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js new file mode 100644 index 0000000000..aa17ab168c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-nanoseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 533, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 528, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 525, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 400, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js new file mode 100644 index 0000000000..f728a4c75f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-non-integer.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Rounding for roundingIncrement option +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = later.since(earlier, { roundingIncrement: 2.5, roundingMode: "trunc" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 truncates to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js new file mode 100644 index 0000000000..74ad0e56dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-out-of-range.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingIncrement option out of range +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: -1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 0.9 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: 1e9 + 1 })); +assert.throws(RangeError, () => later.since(earlier, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js new file mode 100644 index 0000000000..48ae41c282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-seconds.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 22, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 35, 21, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 35, 18, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 35, 12, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 35, 15, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js new file mode 100644 index 0000000000..816763660e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +const explicit = later.since(earlier, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js new file mode 100644 index 0000000000..a8d580d49a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.since step 11: + 11. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => later.since(earlier, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js new file mode 100644 index 0000000000..2c59d6364e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-ceil.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 5], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 18], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -4]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 865], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "ceil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-expand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-expand.js new file mode 100644 index 0000000000..fc0ffaf8e0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-expand.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "expand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 5], [0, 0, 0, 0, -5]], + ["minutes", [0, 0, 0, 0, 4, 18], [0, 0, 0, 0, -4, -18]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 865], [0, 0, 0, 0, -4, -17, -4, -865]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "expand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js new file mode 100644 index 0000000000..2063878a22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-floor.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -5]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -18]], + ["seconds", [0, 0, 0, 0, 4, 17, 4], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -865]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "floor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfCeil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfCeil.js new file mode 100644 index 0000000000..319a618aed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfCeil.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfCeil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfCeil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfEven.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfEven.js new file mode 100644 index 0000000000..b6b3edbf50 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfEven.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfEven". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfEven"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js new file mode 100644 index 0000000000..a44ce32e5c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfExpand.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfExpand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfFloor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfFloor.js new file mode 100644 index 0000000000..560047cf1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfFloor.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfFloor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfFloor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfTrunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfTrunc.js new file mode 100644 index 0000000000..9658dfc732 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-halfTrunc.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "halfTrunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfTrunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js new file mode 100644 index 0000000000..ba57777e2c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => later.since(earlier, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js new file mode 100644 index 0000000000..e1b447c453 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-trunc.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 4], [0, 0, 0, 0, -4, -17, -4]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "trunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js new file mode 100644 index 0000000000..f437428f15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-undefined.js @@ -0,0 +1,93 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "hours" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "hours" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "minutes" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "minutes" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "seconds" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "seconds" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.since(earlier, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.since(later, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js new file mode 100644 index 0000000000..3ccf979f0d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => later.since(earlier, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js new file mode 100644 index 0000000000..28dd00c591 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-invalid-string.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when smallestUnit option not one of the allowed string values +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 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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js new file mode 100644 index 0000000000..c6d998214b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => later.since(earlier, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js new file mode 100644 index 0000000000..ba00b5348c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +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 explicit = later.since(earlier, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = later.since(earlier, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const lambda = later.since(earlier, () => {}); +TemporalHelpers.assertDuration(lambda, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js new file mode 100644 index 0000000000..915b81a772 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.since +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => later.since(earlier, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js new file mode 100644 index 0000000000..86f60c8ed7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/since/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00", + "-000000-12-07T03:24:30+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.since(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-max.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-max.js new file mode 100644 index 0000000000..6e24c81554 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-max.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Maximum allowed duration +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const maxCases = [ + ["P4294967295Y104249991374DT7H36M31.999999999S", "string with max years"], + [{ years: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max years"], + ["P4294967295M104249991374DT7H36M31.999999999S", "string with max weeks"], + [{ months: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max months"], + ["P4294967295W104249991374DT7H36M31.999999999S", "string with max weeks"], + [{ weeks: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max weeks"], + ["P104249991374DT7H36M31.999999999S", "string with max days"], + [{ days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max days"], + ["PT2501999792983H36M31.999999999S", "string with max hours"], + [{ hours: 2501999792983, nanoseconds: 2191999999999 }, "property bag with max hours"], + ["PT150119987579016M31.999999999S", "string with max minutes"], + [{ minutes: 150119987579016, nanoseconds: 31999999999 }, "property bag with max minutes"], + ["PT9007199254740991.999999999S", "string with max seconds"], + [{ seconds: 9007199254740991, nanoseconds: 999999999 }, "property bag with max seconds"], +]; + +for (const [arg, descr] of maxCases) { + const result = instance.subtract(arg); + TemporalHelpers.assertPlainTime(result, 16, 23, 28, 0, 0, 1, `operation succeeds with ${descr}`); +} + +const minCases = [ + ["-P4294967295Y104249991374DT7H36M31.999999999S", "string with min years"], + [{ years: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min years"], + ["-P4294967295M104249991374DT7H36M31.999999999S", "string with min months"], + [{ months: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min months"], + ["-P4294967295W104249991374DT7H36M31.999999999S", "string with min weeks"], + [{ weeks: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min weeks"], + ["-P104249991374DT7H36M31.999999999S", "string with min days"], + [{ days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min days"], + ["-PT2501999792983H36M31.999999999S", "string with min hours"], + [{ hours: -2501999792983, nanoseconds: -2191999999999 }, "property bag with min hours"], + ["-PT150119987579016M31.999999999S", "string with min minutes"], + [{ minutes: -150119987579016, nanoseconds: -31999999999 }, "property bag with min minutes"], + ["-PT9007199254740991.999999999S", "string with min seconds"], + [{ seconds: -9007199254740991, nanoseconds: -999999999 }, "property bag with min seconds"], +]; + +for (const [arg, descr] of minCases) { + const result = instance.subtract(arg); + TemporalHelpers.assertPlainTime(result, 7, 36, 31, 999, 999, 999, `operation succeeds with ${descr}`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-out-of-range.js new file mode 100644 index 0000000000..8227cc217b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-out-of-range.js @@ -0,0 +1,75 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Duration-like argument that is out of range +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const cases = [ + // 2^32 = 4294967296 + ["P4294967296Y", "string with years > max"], + [{ years: 4294967296 }, "property bag with years > max"], + ["-P4294967296Y", "string with years < min"], + [{ years: -4294967296 }, "property bag with years < min"], + ["P4294967296M", "string with months > max"], + [{ months: 4294967296 }, "property bag with months > max"], + ["-P4294967296M", "string with months < min"], + [{ months: -4294967296 }, "property bag with months < min"], + ["P4294967296W", "string with weeks > max"], + [{ weeks: 4294967296 }, "property bag with weeks > max"], + ["-P4294967296W", "string with weeks < min"], + [{ weeks: -4294967296 }, "property bag with weeks < min"], + + // ceil(max safe integer / 86400) = 104249991375 + ["P104249991375D", "string with days > max"], + [{ days: 104249991375 }, "property bag with days > max"], + ["P104249991374DT24H", "string where hours balance into days > max"], + [{ days: 104249991374, hours: 24 }, "property bag where hours balance into days > max"], + ["-P104249991375D", "string with days < min"], + [{ days: -104249991375 }, "property bag with days < min"], + ["-P104249991374DT24H", "string where hours balance into days < min"], + [{ days: -104249991374, hours: -24 }, "property bag where hours balance into days < min"], + + // ceil(max safe integer / 3600) = 2501999792984 + ["PT2501999792984H", "string with hours > max"], + [{ hours: 2501999792984 }, "property bag with hours > max"], + ["PT2501999792983H60M", "string where minutes balance into hours > max"], + [{ hours: 2501999792983, minutes: 60 }, "property bag where minutes balance into hours > max"], + ["-PT2501999792984H", "string with hours < min"], + [{ hours: -2501999792984 }, "property bag with hours < min"], + ["-PT2501999792983H60M", "string where minutes balance into hours < min"], + [{ hours: -2501999792983, minutes: -60 }, "property bag where minutes balance into hours < min"], + + // ceil(max safe integer / 60) = 150119987579017 + ["PT150119987579017M", "string with minutes > max"], + [{ minutes: 150119987579017 }, "property bag with minutes > max"], + ["PT150119987579016M60S", "string where seconds balance into minutes > max"], + [{ minutes: 150119987579016, seconds: 60 }, "property bag where seconds balance into minutes > max"], + ["-PT150119987579017M", "string with minutes < min"], + [{ minutes: -150119987579017 }, "property bag with minutes < min"], + ["-PT150119987579016M60S", "string where seconds balance into minutes < min"], + [{ minutes: -150119987579016, seconds: -60 }, "property bag where seconds balance into minutes < min"], + + // 2^53 = 9007199254740992 + ["PT9007199254740992S", "string with seconds > max"], + [{ seconds: 9007199254740992 }, "property bag with seconds > max"], + [{ seconds: 9007199254740991, milliseconds: 1000 }, "property bag where milliseconds balance into seconds > max"], + [{ seconds: 9007199254740991, microseconds: 1000000 }, "property bag where microseconds balance into seconds > max"], + [{ seconds: 9007199254740991, nanoseconds: 1000000000 }, "property bag where nanoseconds balance into seconds > max"], + ["-PT9007199254740992S", "string with seconds < min"], + [{ seconds: -9007199254740992 }, "property bag with seconds < min"], + [{ seconds: -9007199254740991, milliseconds: -1000 }, "property bag where milliseconds balance into seconds < min"], + [{ seconds: -9007199254740991, microseconds: -1000000 }, "property bag where microseconds balance into seconds < min"], + [{ seconds: -9007199254740991, nanoseconds: -1000000000 }, "property bag where nanoseconds balance into seconds < min"], +]; + +for (const [arg, descr] of cases) { + assert.throws(RangeError, () => instance.subtract(arg), `${descr} is out of range`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-precision-exact-numerical-values.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-precision-exact-numerical-values.js new file mode 100644 index 0000000000..a595fa204f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration-precision-exact-numerical-values.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Duration-like argument performs the range check with minimal floating point + precision loss +features: [Temporal] +---*/ + +// Based on a test case by André Bargull + +const instance = new Temporal.PlainTime(); + +const cases = [ + [ + { + milliseconds: 4503599627370497_000, // ℝ(𝔽(4503599627370497000)) = 4503599627370497024 + microseconds: 4503599627370495_000000, // ℝ(𝔽(4503599627370495000000)) = 4503599627370494951424 + }, + // 4503599627370497024 / 1000 + 4503599627370494951424 / 1000000 is + // 9007199254740991.975424, which is below the limit of 2**53 + "case where floating point inaccuracy brings total below limit, positive" + ], + [ + { + milliseconds: -4503599627370497_000, + microseconds: -4503599627370495_000000, + }, + "case where floating point inaccuracy brings total below limit, negative" + ], +]; + +for (const [arg, descr] of cases) { + instance.subtract(arg); // should not throw +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js new file mode 100644 index 0000000000..99c1990791 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-duration.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.subtract +description: Duration arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const duration = Temporal.Duration.from("PT16H"); +TemporalHelpers.assertPlainTime(plainTime.subtract(duration), + 23, 23, 30, 123, 456, 789); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js new file mode 100644 index 0000000000..43588561a9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-higher-units.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Higher units are ignored. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const values = [ + new Temporal.Duration(0, 0, 0, 1), + new Temporal.Duration(0, 0, 1), + new Temporal.Duration(0, 1), + new Temporal.Duration(1), + { days: 1 }, + { weeks: 1 }, + { months: 1 }, + { years: 1 }, + "P1D", + "P1W", + "P1M", + "P1Y", +]; +for (const value of values) { + TemporalHelpers.assertPlainTime(plainTime.subtract(value), + 15, 23, 30, 123, 456, 789); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-invalid-property.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-invalid-property.js new file mode 100644 index 0000000000..6fab0a1c32 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-invalid-property.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: temporalDurationLike object must contain at least one correctly spelled property +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +assert.throws( + TypeError, + () => instance.subtract({}), + "Throws TypeError if no property is present" +); + +assert.throws( + TypeError, + () => instance.subtract({ nonsense: true }), + "Throws TypeError if no recognized property is present" +); + +assert.throws( + TypeError, + () => instance.subtract({ sign: 1 }), + "Sign property is not recognized" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-mixed-sign.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-mixed-sign.js new file mode 100644 index 0000000000..234ad0fedb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-mixed-sign.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Positive and negative values in the temporalDurationLike argument are not acceptable +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +assert.throws( + RangeError, + () => instance.subtract({ hours: 1, minutes: -30 }), + `mixed positive and negative values always throw` +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js new file mode 100644 index 0000000000..c77ced8f6b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-not-object.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Passing a primitive other than string to subtract() throws +features: [Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +assert.throws(TypeError, () => instance.subtract(undefined), "undefined"); +assert.throws(TypeError, () => instance.subtract(null), "null"); +assert.throws(TypeError, () => instance.subtract(true), "boolean"); +assert.throws(RangeError, () => instance.subtract(""), "empty string"); +assert.throws(TypeError, () => instance.subtract(Symbol()), "Symbol"); +assert.throws(TypeError, () => instance.subtract(7), "number"); +assert.throws(TypeError, () => instance.subtract(7n), "bigint"); +assert.throws(TypeError, () => instance.subtract([]), "array"); +assert.throws(TypeError, () => instance.subtract(() => {}), "function"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js new file mode 100644 index 0000000000..38290a6bf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-object.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Plain object arguments are supported. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime.subtract({ hours: 16 }), + 23, 23, 30, 123, 456, 789, "subtract 16 hours across midnight boundary"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ minutes: 45 }), + 14, 38, 30, 123, 456, 789, "subtract 45 minutes"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ seconds: 45 }), + 15, 22, 45, 123, 456, 789, "subtract 45 seconds"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ milliseconds: 800 }), + 15, 23, 29, 323, 456, 789, "subtract 800 milliseconds"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ microseconds: 800 }), + 15, 23, 30, 122, 656, 789, "subtract 800 microseconds"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ nanoseconds: 800 }), + 15, 23, 30, 123, 455, 989, "subtract 800 nanoseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("23:23:30.123456789").subtract({ hours: -16 }), + 15, 23, 30, 123, 456, 789, "subtract -16 hours across midnight boundary"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("14:38:30.123456789").subtract({ minutes: -45 }), + 15, 23, 30, 123, 456, 789, "subtract -45 minutes"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:22:45.123456789").subtract({ seconds: -45 }), + 15, 23, 30, 123, 456, 789, "subtract -45 seconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:29.323456789").subtract({ milliseconds: -800 }), + 15, 23, 30, 123, 456, 789, "subtract -800 milliseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.122656789").subtract({ microseconds: -800 }), + 15, 23, 30, 123, 456, 789, "subtract -800 microseconds"); +TemporalHelpers.assertPlainTime(Temporal.PlainTime.from("15:23:30.123455989").subtract({ nanoseconds: -800 }), + 15, 23, 30, 123, 456, 789, "subtract -800 nanoseconds"); +TemporalHelpers.assertPlainTime(plainTime.subtract({ minute: 1, hours: 1 }), + 14, 23, 30, 123, 456, 789, "misspelled property is ignored"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-singular-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-singular-properties.js new file mode 100644 index 0000000000..6bb1a76f9f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-singular-properties.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Singular properties in the property bag are always ignored +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); + +[ + { 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, () => instance.subtract(badObject), + "Throw TypeError if temporalDurationLike is not valid"); +}); + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-duration-too-large.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-duration-too-large.js new file mode 100644 index 0000000000..4d26a245df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-duration-too-large.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + ParseTemporalDurationString throws a RangeError when the result is too large. +features: [Temporal] +---*/ + +// Number string too long to be representable as a Number value. +var ones = "1".repeat(1000); +assert.sameValue(Number(ones), Infinity); + +var time = new Temporal.PlainTime(); +var str = "PT" + ones + "S"; + +assert.throws(RangeError, () => time.subtract(str)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js new file mode 100644 index 0000000000..c0b706f506 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-fractional-units-rounding-mode.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Strings with fractional duration units are rounded with the correct rounding mode +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const midnight = new Temporal.PlainTime(); + +TemporalHelpers.assertPlainTime(midnight.subtract("PT1.03125H"), 22, 58, 7, 500, 0, 0, + "positive fractional units rounded with correct rounding mode"); +TemporalHelpers.assertPlainTime(midnight.subtract("-PT1.03125H"), 1, 1, 52, 500, 0, 0, + "negative fractional units rounded with correct rounding mode"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js new file mode 100644 index 0000000000..d11506a0cc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string-negative-fractional-units.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Strings with fractional duration units are treated with the correct sign +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const resultHours = instance.subtract("-PT24.567890123H"); +TemporalHelpers.assertPlainTime(resultHours, 0, 34, 4, 404, 442, 800, "negative fractional hours"); + +const resultMinutes = instance.subtract("-PT1440.567890123M"); +TemporalHelpers.assertPlainTime(resultMinutes, 0, 0, 34, 73, 407, 380, "negative fractional minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js new file mode 100644 index 0000000000..5e05b5bae6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/argument-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: A string is parsed into the correct object when passed as the argument +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); +const result = instance.subtract("PT3M"); +TemporalHelpers.assertPlainTime(result, 12, 31, 56, 987, 654, 321); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js new file mode 100644 index 0000000000..f0712a3d66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/balance-negative-time-units.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-addtime step 8: + 8. Return ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal.plaintime.prototype.subtract step 4: + 4. Let _result_ be ? AddTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], −_duration_.[[Hours]], −_duration_.[[Minutes]], −_duration_.[[Seconds]], −_duration_.[[Milliseconds]], −_duration_.[[Microseconds]], −_duration_.[[Nanoseconds]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result1, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result2, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result3, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result4, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result5, 0, 59, 1, 1, 1, 1, "minutes balance"); + +const result6 = time.subtract(new Temporal.Duration(0, 0, 0, 0, 2)); +TemporalHelpers.assertPlainTime(result6, 23, 1, 1, 1, 1, 1, "hours mod 24"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/branding.js new file mode 100644 index 0000000000..c51391219d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const subtract = Temporal.PlainTime.prototype.subtract; + +assert.sameValue(typeof subtract, "function"); + +const args = [new Temporal.Duration(0, 0, 0, 0, 5)]; + +assert.throws(TypeError, () => subtract.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => subtract.apply(null, args), "null"); +assert.throws(TypeError, () => subtract.apply(true, args), "true"); +assert.throws(TypeError, () => subtract.apply("", args), "empty string"); +assert.throws(TypeError, () => subtract.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => subtract.apply(1, args), "1"); +assert.throws(TypeError, () => subtract.apply({}, args), "plain object"); +assert.throws(TypeError, () => subtract.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => subtract.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js new file mode 100644 index 0000000000..ee2826cf6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Tests that Temporal.PlainTime.prototype.subtract + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.subtract), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.subtract), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.subtract), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.subtract.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..27a8ae2ee7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.subtract throws a RangeError if any value in a property bag is Infinity +esid: sec-temporal.plaintime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js new file mode 100644 index 0000000000..14a130a438 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Temporal.PlainTime.prototype.subtract.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.subtract, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js new file mode 100644 index 0000000000..3bc47f8d59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Temporal.PlainTime.prototype.subtract.name is "subtract". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.subtract, "name", { + value: "subtract", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..e9f557b0ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/negative-infinity-throws-rangeerror.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Temporal.PlainTime.prototype.subtract throws a RangeError if any value in a property bag is -Infinity +esid: sec-temporal.plaintime.prototype.subtract +features: [Temporal] +---*/ + +const overflows = ["constrain", "reject"]; +const fields = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; + +const instance = Temporal.PlainTime.from({ hour: 12, minute: 34, second: 56, millisecond: 987, microsecond: 654, nanosecond: 321 }); + +overflows.forEach((overflow) => { + fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { overflow })); + }); +}); + +let calls = 0; +const obj = { + valueOf() { + calls++; + return -Infinity; + } +}; + +overflows.forEach((overflow) => { + fields.forEach((field) => { + calls = 0; + assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { overflow })); + assert.sameValue(calls, 1, "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js new file mode 100644 index 0000000000..fd5246180e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: A non-integer value for any recognized property in the property bag, throws a RangeError +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15, 30, 45, 987, 654, 321); +const fields = [ + "years", + "months", + "weeks", + "days", + "hours", + "minutes", + "seconds", + "milliseconds", + "microseconds", + "nanoseconds", +]; +fields.forEach((field) => { + assert.throws(RangeError, () => instance.subtract({ [field]: 1.5 })); + assert.throws(RangeError, () => instance.subtract({ [field]: -1.5 })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js new file mode 100644 index 0000000000..c382bb0251 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Temporal.PlainTime.prototype.subtract does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.subtract(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.subtract), false, + "isConstructor(Temporal.PlainTime.prototype.subtract)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js new file mode 100644 index 0000000000..49d07b34ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/options-ignored.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Options argument is ignored. +includes: [temporalHelpers.js] +features: [Symbol, Temporal] +---*/ + +const values = [ + undefined, + null, + true, + "hello", + Symbol("foo"), + 1, + 1n, + {}, + () => {}, + { get overflow() { throw new Test262Error("should not get overflow") } }, +]; + +const time = Temporal.PlainTime.from("15:23:30.123456789"); +for (const options of values) { + TemporalHelpers.assertPlainTime(time.subtract({ hours: 1 }, options), + 14, 23, 30, 123, 456, 789); +} + + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js new file mode 100644 index 0000000000..c8c81fcc3b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations.js @@ -0,0 +1,62 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Properties on an object passed to subtract() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + "get fields.days", + "get fields.days.valueOf", + "call fields.days.valueOf", + "get fields.hours", + "get fields.hours.valueOf", + "call fields.hours.valueOf", + "get fields.microseconds", + "get fields.microseconds.valueOf", + "call fields.microseconds.valueOf", + "get fields.milliseconds", + "get fields.milliseconds.valueOf", + "call fields.milliseconds.valueOf", + "get fields.minutes", + "get fields.minutes.valueOf", + "call fields.minutes.valueOf", + "get fields.months", + "get fields.months.valueOf", + "call fields.months.valueOf", + "get fields.nanoseconds", + "get fields.nanoseconds.valueOf", + "call fields.nanoseconds.valueOf", + "get fields.seconds", + "get fields.seconds.valueOf", + "call fields.seconds.valueOf", + "get fields.weeks", + "get fields.weeks.valueOf", + "call fields.weeks.valueOf", + "get fields.years", + "get fields.years.valueOf", + "call fields.years.valueOf", +]; +const actual = []; +const fields = TemporalHelpers.propertyBagObserver(actual, { + years: 1, + months: 1, + weeks: 1, + days: 1, + hours: 1, + minutes: 1, + seconds: 1, + milliseconds: 1, + microseconds: 1, + nanoseconds: 1, +}, "fields"); +const result = instance.subtract(fields); +TemporalHelpers.assertPlainTime(result, 11, 33, 55, 986, 653, 320); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-1.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-1.js new file mode 100644 index 0000000000..3b9836b044 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-1.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Duration components are precise mathematical integers. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let duration = Temporal.Duration.from({ + microseconds: Number.MIN_SAFE_INTEGER, + nanoseconds: -1000, +}); + +let time = Temporal.PlainTime.from({ + microsecond: 1, +}); + +let result = time.subtract(duration); + +TemporalHelpers.assertPlainTime(result, 23, 47, 34, 740, 993, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-2.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-2.js new file mode 100644 index 0000000000..c216bd6231 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-2.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: > + Duration components are precise mathematical integers. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +let duration = Temporal.Duration.from({ + seconds: -Number.MAX_SAFE_INTEGER, + nanoseconds: -999_999_999, +}); + +let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0); + +let result = time.subtract(duration); + +TemporalHelpers.assertPlainTime(result, 7, 36, 31, 999, 999, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js new file mode 100644 index 0000000000..7d4e360a6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: The "subtract" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.subtract, + "function", + "`typeof PlainTime.prototype.subtract` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "subtract", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js new file mode 100644 index 0000000000..e9c47a0666 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.subtract +description: Objects of a subclass are never created as return values for subtract() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "subtract", + [{ nanoseconds: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 320), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/basic.js new file mode 100644 index 0000000000..e3cbd04d1e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/basic.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Basic behavior for toJSON +features: [Temporal] +---*/ + +const tests = [ + [new Temporal.PlainTime(5, 3, 1), "05:03:01"], + [new Temporal.PlainTime(15, 23), "15:23:00"], + [new Temporal.PlainTime(15, 23, 30), "15:23:30"], + [new Temporal.PlainTime(15, 23, 30, 123, 400), "15:23:30.1234"], +]; + +const options = new Proxy({}, { + get() { throw new Test262Error("should not get properties off argument") } +}); +for (const [time, expected] of tests) { + assert.sameValue(time.toJSON(), expected, "toJSON without argument"); + assert.sameValue(time.toJSON(options), expected, "toJSON with argument"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/branding.js new file mode 100644 index 0000000000..21624123db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toJSON = Temporal.PlainTime.prototype.toJSON; + +assert.sameValue(typeof toJSON, "function"); + +assert.throws(TypeError, () => toJSON.call(undefined), "undefined"); +assert.throws(TypeError, () => toJSON.call(null), "null"); +assert.throws(TypeError, () => toJSON.call(true), "true"); +assert.throws(TypeError, () => toJSON.call(""), "empty string"); +assert.throws(TypeError, () => toJSON.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toJSON.call(1), "1"); +assert.throws(TypeError, () => toJSON.call({}), "plain object"); +assert.throws(TypeError, () => toJSON.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => toJSON.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js new file mode 100644 index 0000000000..c2a661a303 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: > + Tests that Temporal.PlainTime.prototype.toJSON + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toJSON), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toJSON), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toJSON), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toJSON.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js new file mode 100644 index 0000000000..5c4ca090f3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Temporal.PlainTime.prototype.toJSON.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toJSON, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js new file mode 100644 index 0000000000..60560473d5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: Temporal.PlainTime.prototype.toJSON.name is "toJSON". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toJSON, "name", { + value: "toJSON", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js new file mode 100644 index 0000000000..ef77906631 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: > + Temporal.PlainTime.prototype.toJSON does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toJSON(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toJSON), false, + "isConstructor(Temporal.PlainTime.prototype.toJSON)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js new file mode 100644 index 0000000000..56d7e40457 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tojson +description: The "toJSON" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toJSON, + "function", + "`typeof PlainTime.prototype.toJSON` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toJSON", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toJSON/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/branding.js new file mode 100644 index 0000000000..2401d31297 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toLocaleString = Temporal.PlainTime.prototype.toLocaleString; + +assert.sameValue(typeof toLocaleString, "function"); + +assert.throws(TypeError, () => toLocaleString.call(undefined), "undefined"); +assert.throws(TypeError, () => toLocaleString.call(null), "null"); +assert.throws(TypeError, () => toLocaleString.call(true), "true"); +assert.throws(TypeError, () => toLocaleString.call(""), "empty string"); +assert.throws(TypeError, () => toLocaleString.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toLocaleString.call(1), "1"); +assert.throws(TypeError, () => toLocaleString.call({}), "plain object"); +assert.throws(TypeError, () => toLocaleString.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => toLocaleString.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js new file mode 100644 index 0000000000..5cf924222c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + Tests that Temporal.PlainTime.prototype.toLocaleString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toLocaleString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toLocaleString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toLocaleString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toLocaleString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js new file mode 100644 index 0000000000..2da8dbc59d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Temporal.PlainTime.prototype.toLocaleString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toLocaleString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js new file mode 100644 index 0000000000..c736160c0c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: Temporal.PlainTime.prototype.toLocaleString.name is "toLocaleString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toLocaleString, "name", { + value: "toLocaleString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js new file mode 100644 index 0000000000..0e7938a0fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + Temporal.PlainTime.prototype.toLocaleString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toLocaleString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toLocaleString), false, + "isConstructor(Temporal.PlainTime.prototype.toLocaleString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js new file mode 100644 index 0000000000..8ed43ab577 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: The "toLocaleString" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toLocaleString, + "function", + "`typeof PlainTime.prototype.toLocaleString` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toLocaleString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js new file mode 100644 index 0000000000..59c032d396 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Kate Miháliková. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tolocalestring +description: > + toLocaleString return a string. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.sameValue(typeof time.toLocaleString("en", { timeStyle: "short" }), "string"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toLocaleString/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..aaf98aa359 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-builtin-calendar-no-array-iteration.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Calling the method with a property bag argument with a builtin calendar causes + no observable array iteration when getting the calendar fields. +features: [Temporal] +---*/ + +const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function arrayIterator() { + throw new Test262Error("Array should not be iterated"); +} + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.toPlainDateTime(arg); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..fb8706493b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Calendar.dateFromFields method is called with a null-prototype fields object +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.toPlainDateTime(arg); +assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..ba733a7bd9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-constructor-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(RangeError, () => instance.toPlainDateTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..671a32ba83 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-duplicate-calendar-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const extra_fields of [['foo', 'foo'], ['day'], ['month'], ['monthCode'], ['year']]) { + const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields); + const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar }; + const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => instance.toPlainDateTime(arg)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-leap-second.js new file mode 100644 index 0000000000..df8483e7b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-leap-second.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Leap second is a valid ISO string for PlainDate +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.toPlainDateTime(arg); +TemporalHelpers.assertPlainDateTime( + result1, + 2016, 12, "M12", 31, 12, 34, 56, 987, 654, 321, + "leap second is a valid ISO string for PlainDate" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.toPlainDateTime(arg); +TemporalHelpers.assertPlainDateTime( + result2, + 2016, 12, "M12", 31, 12, 34, 56, 987, 654, 321, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-number.js new file mode 100644 index 0000000000..aee435340f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.toPlainDateTime(arg), + 'Numbers cannot be used in place of an ISO string for PlainDate' + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js new file mode 100644 index 0000000000..2d5bdfb37e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-plaindatetime.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.toplaindatetime +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const time = new Temporal.PlainTime(6, 54, 32, 123, 456, 789); + const result = time.toPlainDateTime(datetime); + TemporalHelpers.assertPlainDateTime(result, 2000, 5, "M05", 2, 6, 54, 32, 123, 456, 789); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..34dd11bf93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: The calendar name is case-insensitive +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toPlainDateTime(arg); +TemporalHelpers.assertPlainDateTime(result, 1976, 11, "M11", 18, 12, 34, 56, 987, 654, 321, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..9beb64271e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Leap second is a valid ISO string for a calendar in a property bag +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toPlainDateTime(arg); +TemporalHelpers.assertPlainDateTime( + result, + 1976, 11, "M11", 18, 12, 34, 56, 987, 654, 321, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..407773adb4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.PlainDate(1976, 11, 18); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.toPlainDateTime(arg), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..6edf8a1789 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-string.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: A calendar ID is valid input for Calendar +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toPlainDateTime(arg); +TemporalHelpers.assertPlainDateTime(result, 1976, 11, "M11", 18, 12, 34, 56, 987, 654, 321, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..7924805b00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-wrong-type.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Appropriate error thrown when a calendar property from a property bag cannot + be converted to a calendar object or string +features: [BigInt, Symbol, Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [calendar, description] of primitiveTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws( + typeof calendar === 'string' ? RangeError : TypeError, + () => instance.toPlainDateTime(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object that doesn't implement the protocol"], + [new Temporal.TimeZone("UTC"), "time zone instance"], + [Temporal.Calendar, "Temporal.Calendar, object"], + [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields() +]; + +for (const [calendar, description] of typeErrorTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws(TypeError, () => instance.toPlainDateTime(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..f9ba398d5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-propertybag-calendar-year-zero.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T17:45", + "-000000-10-31T17:45Z", + "-000000-10-31T17:45+01:00", + "-000000-10-31T17:45+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..fd70a10ff5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-proto-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(RangeError, () => instance.toPlainDateTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..b7ab3b08c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-calendar-annotation.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[u-ca=iso8601]", "without time or time zone"], + ["2000-05-02[UTC][u-ca=iso8601]", "with time zone and no time"], + ["2000-05-02T15:23[u-ca=iso8601]", "without time zone"], + ["2000-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"], + ["2000-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"], + ["2000-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["2000-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toPlainDateTime(arg); + + TemporalHelpers.assertPlainDateTime( + result, + 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..88e313cf0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-critical-unknown-annotation.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..6e64c39c15 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-date-with-utc-offset.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const validStrings = [ + "2000-05-02T00+00:00", + "2000-05-02T00+00:00[UTC]", + "2000-05-02T00+00:00[!UTC]", + "2000-05-02T00-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.toPlainDateTime(arg); + + TemporalHelpers.assertPlainDateTime( + result, + 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + `"${arg}" is a valid UTC offset with time for PlainDate` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js new file mode 100644 index 0000000000..519b9ff9be --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..2208411476 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..4f47d2457f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-multiple-time-zone.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-separators.js new file mode 100644 index 0000000000..8325711849 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-separators.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02T15:23", "uppercase T"], + ["2000-05-02t15:23", "lowercase T"], + ["2000-05-02 15:23", "space between date and time"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toPlainDateTime(arg); + + TemporalHelpers.assertPlainDateTime( + result, + 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..9af036f12c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-time-zone-annotation.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[Asia/Kolkata]", "named, with no time"], + ["2000-05-02[!Europe/Vienna]", "named, with ! and no time"], + ["2000-05-02[+00:00]", "numeric, with no time"], + ["2000-05-02[!-02:30]", "numeric, with ! and no time"], + ["2000-05-02T15:23[America/Sao_Paulo]", "named, with no offset"], + ["2000-05-02T15:23[!Asia/Tokyo]", "named, with ! and no offset"], + ["2000-05-02T15:23[-02:30]", "numeric, with no offset"], + ["2000-05-02T15:23[!+00:00]", "numeric, with ! and no offset"], + ["2000-05-02T15:23+00:00[America/New_York]", "named, with offset"], + ["2000-05-02T15:23+00:00[!UTC]", "named, with offset and !"], + ["2000-05-02T15:23+00:00[+01:00]", "numeric, with offset"], + ["2000-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toPlainDateTime(arg); + + TemporalHelpers.assertPlainDateTime( + result, + 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..0fb9958f8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-unknown-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Various forms of unknown annotation +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["2000-05-02[foo=bar]", "without time"], + ["2000-05-02T15:23[foo=bar]", "alone"], + ["2000-05-02T15:23[UTC][foo=bar]", "with time zone"], + ["2000-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"], + ["2000-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["2000-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toPlainDateTime(arg); + + TemporalHelpers.assertPlainDateTime( + result, + 2000, 5, "M05", 2, 12, 34, 56, 987, 654, 321, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..4e47c1b5cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-wrong-type.js new file mode 100644 index 0000000000..95387bf637 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainDate +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.toPlainDateTime(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainDate, "Temporal.PlainDate, object"], + [Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.toPlainDateTime(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..39f6296bda --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-convert.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: An exception from TimeZone#getOffsetNanosecondsFor() is propagated. +features: [Temporal] +---*/ + +class TZ extends Temporal.TimeZone { + constructor() { super("UTC") } + getOffsetNanosecondsFor() { throw new Test262Error() } +} + +const tz = new TZ(); +const arg = new Temporal.ZonedDateTime(0n, tz); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(Test262Error, () => instance.toPlainDateTime(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..a7ea2c308e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-slots.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Getters are not called when converting a ZonedDateTime to a PlainDate. +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.ZonedDateTime.prototype); +const getters = ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "calendar"]; + +for (const property of getters) { + Object.defineProperty(Temporal.ZonedDateTime.prototype, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); +} + +const arg = new Temporal.ZonedDateTime(0n, "UTC"); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +instance.toPlainDateTime(arg); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..996ac97964 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..5757a1d253 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toPlainDateTime(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..92bff3ca6d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..b1b91f30fa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.toPlainDateTime(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js new file mode 100644 index 0000000000..995467100a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.toplaindatetime +description: Basic tests for toPlainDateTime(). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("11:30:23.123456789"); + +const plainDate = plainTime.toPlainDateTime(Temporal.PlainDate.from("1976-11-18")); +TemporalHelpers.assertPlainDateTime(plainDate, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "PlainDate"); + +const optionBag = plainTime.toPlainDateTime({ year: 1976, month: 11, day: 18 }); +TemporalHelpers.assertPlainDateTime(optionBag, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "option bag"); + +const string = plainTime.toPlainDateTime("1976-11-18"); +TemporalHelpers.assertPlainDateTime(string, 1976, 11, "M11", 18, 11, 30, 23, 123, 456, 789, "string"); + +assert.throws(TypeError, () => plainTime.toPlainDateTime({ year: 1976 }), "missing properties"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/branding.js new file mode 100644 index 0000000000..724c37070f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toPlainDateTime = Temporal.PlainTime.prototype.toPlainDateTime; + +assert.sameValue(typeof toPlainDateTime, "function"); + +const args = [new Temporal.PlainDate(2022, 6, 22)]; + +assert.throws(TypeError, () => toPlainDateTime.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => toPlainDateTime.apply(null, args), "null"); +assert.throws(TypeError, () => toPlainDateTime.apply(true, args), "true"); +assert.throws(TypeError, () => toPlainDateTime.apply("", args), "empty string"); +assert.throws(TypeError, () => toPlainDateTime.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => toPlainDateTime.apply(1, args), "1"); +assert.throws(TypeError, () => toPlainDateTime.apply({}, args), "plain object"); +assert.throws(TypeError, () => toPlainDateTime.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => toPlainDateTime.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js new file mode 100644 index 0000000000..9242d0b4a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Tests that Temporal.PlainTime.prototype.toPlainDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toPlainDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toPlainDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toPlainDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toPlainDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..cbca1c086f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js new file mode 100644 index 0000000000..93ae2c6dc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-fields-iterable.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const time = new Temporal.PlainTime(13, 3); +const calendar = TemporalHelpers.calendarFieldsIterable(); +time.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js new file mode 100644 index 0000000000..9ccbd4fc03 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.toplaindatetime step 3: + 3. Set _temporalDate_ to ? ToTemporalDate(_temporalDate_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const time = new Temporal.PlainTime(13, 3); + const result = time.toPlainDateTime({ year: 2000, month: 5, day: 3, calendar: temporalObject }); + assert.sameValue(result.getCalendar(), calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..84a2e311a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.toplaindatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, [prop]: inf }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toPlainDateTime({ ...base, [prop]: obj })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js new file mode 100644 index 0000000000..a10aff33cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Temporal.PlainTime.prototype.toPlainDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toPlainDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/limits.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/limits.js new file mode 100644 index 0000000000..d2561e05c6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/limits.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Checking limits of representable PlainDateTime +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const midnight = new Temporal.PlainTime(0, 0); +const firstNs = new Temporal.PlainTime(0, 0, 0, 0, 0, 1); +const lastNs = new Temporal.PlainTime(23, 59, 59, 999, 999, 999); +const min = new Temporal.PlainDate(-271821, 4, 19); +const max = new Temporal.PlainDate(275760, 9, 13); + +assert.throws( + RangeError, + () => midnight.toPlainDateTime(min), + "Cannot go below representable limit" +); + +TemporalHelpers.assertPlainDateTime( + midnight.toPlainDateTime(max), + 275760, 9, "M09", 13, 0, 0, 0, 0, 0, 0, + "Midnight of maximum representable PlainDate" +); + +TemporalHelpers.assertPlainDateTime( + firstNs.toPlainDateTime(min), + -271821, 4, "M04", 19, 0, 0, 0, 0, 0, 1, + "Computing the minimum (earliest) representable PlainDateTime" +); + +TemporalHelpers.assertPlainDateTime( + lastNs.toPlainDateTime(max), + 275760, 9, "M09", 13, 23, 59, 59, 999, 999, 999, + "Computing the maximum (latest) representable PlainDateTime" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js new file mode 100644 index 0000000000..830ca10999 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Temporal.PlainTime.prototype.toPlainDateTime.name is "toPlainDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toPlainDateTime, "name", { + value: "toPlainDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js new file mode 100644 index 0000000000..38b8e598ef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: > + Temporal.PlainTime.prototype.toPlainDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toPlainDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toPlainDateTime), false, + "isConstructor(Temporal.PlainTime.prototype.toPlainDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js new file mode 100644 index 0000000000..ecc3c8e55a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: The "toPlainDateTime" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toPlainDateTime, + "function", + "`typeof PlainTime.prototype.toPlainDateTime` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toPlainDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js new file mode 100644 index 0000000000..090c19d1eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toPlainDateTime/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.toplaindatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T00:45", + "-000000-10-31T00:45+01:00", + "-000000-10-31T00:45+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toPlainDateTime(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js new file mode 100644 index 0000000000..d43372e50f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/basic.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Basic tests for toString() +features: [Temporal] +---*/ + +assert.sameValue(new Temporal.PlainTime(15, 23).toString(), "15:23:00"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30).toString(), "15:23:30"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123).toString(), "15:23:30.123"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 400).toString(), "15:23:30.1234"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 456).toString(), "15:23:30.123456"); +assert.sameValue(new Temporal.PlainTime(15, 23, 30, 123, 456, 789).toString(), "15:23:30.123456789"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/branding.js new file mode 100644 index 0000000000..cd2d2e6171 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toString = Temporal.PlainTime.prototype.toString; + +assert.sameValue(typeof toString, "function"); + +assert.throws(TypeError, () => toString.call(undefined), "undefined"); +assert.throws(TypeError, () => toString.call(null), "null"); +assert.throws(TypeError, () => toString.call(true), "true"); +assert.throws(TypeError, () => toString.call(""), "empty string"); +assert.throws(TypeError, () => toString.call(Symbol()), "symbol"); +assert.throws(TypeError, () => toString.call(1), "1"); +assert.throws(TypeError, () => toString.call({}), "plain object"); +assert.throws(TypeError, () => toString.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => toString.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js new file mode 100644 index 0000000000..c540a97479 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: > + Tests that Temporal.PlainTime.prototype.toString + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toString), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toString), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toString), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toString.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js new file mode 100644 index 0000000000..4468ac3f39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: auto value for fractionalSecondDigits option +features: [Temporal] +---*/ + +const tests = [ + [new Temporal.PlainTime(5, 3, 1), "05:03:01"], + [new Temporal.PlainTime(15, 23), "15:23:00"], + [new Temporal.PlainTime(15, 23, 30), "15:23:30"], + [new Temporal.PlainTime(15, 23, 30, 123, 400), "15:23:30.1234"], +]; + +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"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js new file mode 100644 index 0000000000..9f6d4b7454 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option not one of the allowed string values +info: | + sec-getstringornumberoption step 4: + 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.plaintime.prototype.tostring step 4: + 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", "auto\0"]) { + assert.throws(RangeError, () => time.toString({ fractionalSecondDigits }), + `"${fractionalSecondDigits}" is not a valid value for fractionalSecondDigits`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js new file mode 100644 index 0000000000..ec1a8a2903 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-getstringornumberoption step 2: + 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 ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); +assert.throws(RangeError, () => time.toString({ fractionalSecondDigits: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js new file mode 100644 index 0000000000..2a0eefadbf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Rounding for fractionalSecondDigits option +info: | + sec-getstringornumberoption step 3.b: + b. Return floor(ℝ(_value_)). + 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 ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +let string = time.toString({ fractionalSecondDigits: 2.5 }); +assert.sameValue(string, "12:34:56.98", "fractionalSecondDigits 2.5 floors to 2"); + +string = time.toString({ fractionalSecondDigits: 9.7 }); +assert.sameValue(string, "12:34:56.987650000", "fractionalSecondDigits 9.7 floors to 9 and is not out of range"); + +assert.throws( + RangeError, + () => time.toString({ fractionalSecondDigits: -0.6 }), + "fractionalSecondDigits -0.6 floors to -1 and is out of range" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js new file mode 100644 index 0000000000..068e608617 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Number for fractionalSecondDigits option +features: [Temporal] +---*/ + +const fewSeconds = new Temporal.PlainTime(5, 3, 1); +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(fewSeconds.toString({ fractionalSecondDigits: 0 }), "05:03:01", + "pads parts with 0"); +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js new file mode 100644 index 0000000000..ca1a79ee64 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: RangeError thrown when fractionalSecondDigits option out of range +info: | + sec-getstringornumberoption step 3.a: + a. If _value_ < _minimum_ or _value_ > _maximum_, throw a *RangeError* exception. + 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 ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js new file mode 100644 index 0000000000..c7b073dfac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for fractionalSecondDigits option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-getstringornumberoption step 2: + 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 ? ToSecondsStringPrecision(_options_). +features: [Temporal] +---*/ + +const tests = [ + [new Temporal.PlainTime(5, 3, 1), "05:03:01"], + [new Temporal.PlainTime(15, 23), "15:23:00"], + [new Temporal.PlainTime(15, 23, 30), "15:23:30"], + [new Temporal.PlainTime(15, 23, 30, 123, 400), "15:23:30.1234"], +]; + +for (const [time, expected] of tests) { + const explicit = time.toString({ fractionalSecondDigits: undefined }); + assert.sameValue(explicit, expected, "default fractionalSecondDigits is auto (property present but undefined)"); + + const implicit = time.toString({}); + assert.sameValue(implicit, expected, "default fractionalSecondDigits is auto (property not present)"); + + const lambda = time.toString(() => {}); + assert.sameValue(lambda, expected, "default fractionalSecondDigits is auto (property not present, function object)"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js new file mode 100644 index 0000000000..ff611b4652 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Type conversions for fractionalSecondDigits option +info: | + sec-getoption steps 8–9: + 8. Else if _type_ is Number, then + a. Set _value_ to ? ToNumber(value). + b. ... + 9. Else, + a. Set _value_ to ? ToString(value). + sec-getstringornumberoption step 2: + 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 ? ToSecondsStringPrecision(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 650, 0); + +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"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js new file mode 100644 index 0000000000..d52b57ed79 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Temporal.PlainTime.prototype.toString.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toString, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js new file mode 100644 index 0000000000..7e418da574 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Temporal.PlainTime.prototype.toString.name is "toString". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toString, "name", { + value: "toString", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js new file mode 100644 index 0000000000..0dc5dd1963 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: > + Temporal.PlainTime.prototype.toString does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toString(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toString), false, + "isConstructor(Temporal.PlainTime.prototype.toString)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js new file mode 100644 index 0000000000..5b488efb27 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-invalid.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const instance = Temporal.PlainTime.from("12:56:32"); +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; + +for (const badOptions of values) { + assert.throws(TypeError, () => instance.toString(badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-object.js new file mode 100644 index 0000000000..ff4fd01393 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-object.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Empty or a function object may be used as options +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const result1 = instance.toString({}); +assert.sameValue( + result1, "00:00:00", + "options may be an empty plain object" +); + +const result2 = instance.toString(() => {}); +assert.sameValue( + result2, "00:00:00", + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js new file mode 100644 index 0000000000..c2f24bac5f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-undefined.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const tests = [ + ["15:23", "15:23:00"], + ["15:23:30", "15:23:30"], + ["15:23:30.1234", "15:23:30.1234"], +]; + +for (const [input, expected] of tests) { + const time = Temporal.PlainTime.from(input); + + const explicit = time.toString(undefined); + assert.sameValue(explicit, expected, "default precision is auto and no rounding"); + + const implicit = time.toString(); + assert.sameValue(implicit, expected, "default precision is auto and no rounding"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js new file mode 100644 index 0000000000..130b55c581 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/order-of-operations.js new file mode 100644 index 0000000000..d417bc719d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/order-of-operations.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Properties on objects passed to toString() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "get options.fractionalSecondDigits", + "get options.fractionalSecondDigits.toString", + "call options.fractionalSecondDigits.toString", + "get options.roundingMode", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit", +]; +const actual = []; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const expectedForSmallestUnit = expected.concat([ + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", +]); + +instance.toString( + TemporalHelpers.propertyBagObserver(actual, { + fractionalSecondDigits: "auto", + roundingMode: "halfExpand", + smallestUnit: "millisecond", + }, "options"), +); +assert.compareArray(actual, expectedForSmallestUnit, "order of operations"); +actual.splice(0); // clear + +instance.toString( + TemporalHelpers.propertyBagObserver(actual, { + fractionalSecondDigits: "auto", + roundingMode: "halfExpand", + smallestUnit: undefined, + }, "options"), +); +assert.compareArray(actual, expected, "order of operations with smallestUnit undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js new file mode 100644 index 0000000000..10428d6fc5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: The "toString" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toString, + "function", + "`typeof PlainTime.prototype.toString` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toString", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js new file mode 100644 index 0000000000..8b5b2cb4ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Rounding can cross midnight +features: [Temporal] +---*/ + +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"); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js new file mode 100644 index 0000000000..5d72280641 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: ceil value for roundingMode option +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 (with 6 digits from smallestUnit)"); + +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: "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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-expand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-expand.js new file mode 100644 index 0000000000..29a4b20c23 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-expand.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: expand value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "expand" }); +assert.sameValue(result1, "12:34:56.123988", + "roundingMode is expand (with 6 digits from smallestUnit)"); + +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "expand" }); +assert.sameValue(result2, "12:34:56.123988", + "roundingMode is expand (with 6 digits from fractionalSecondDigits)"); + +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "expand" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is expand (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "expand" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is expand (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "expand" }); +assert.sameValue(result5, "12:34:57", + "roundingMode is expand (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "expand" }); +assert.sameValue(result6, "12:34:57", + "roundingMode is expand (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "expand" }); +assert.sameValue(result7, "12:35", "roundingMode is expand (round to minute)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js new file mode 100644 index 0000000000..e169a3d814 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: floor value for roundingMode option +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 (with 6 digits from smallestUnit)"); + +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: "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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfCeil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfCeil.js new file mode 100644 index 0000000000..4fa20cfcd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfCeil.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfCeil value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfCeil" }); +assert.sameValue(result1, "12:34:56.123988", + "roundingMode is halfCeil (with 6 digits from smallestUnit)"); + +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "halfCeil" }); +assert.sameValue(result2, "12:34:56.123988", + "roundingMode is halfCeil (with 6 digits from fractionalSecondDigits)"); + +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfCeil" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is halfCeil (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "halfCeil" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is halfCeil (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "halfCeil" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is halfCeil (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "halfCeil" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is halfCeil (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "halfCeil" }); +assert.sameValue(result7, "12:35", "roundingMode is halfCeil (round to minute)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfEven.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfEven.js new file mode 100644 index 0000000000..4740838f6e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfEven.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfEven value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfEven" }); +assert.sameValue(result1, "12:34:56.123988", + "roundingMode is halfEven (with 6 digits from smallestUnit)"); + +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "halfEven" }); +assert.sameValue(result2, "12:34:56.123988", + "roundingMode is halfEven (with 6 digits from fractionalSecondDigits)"); + +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfEven" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is halfEven (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "halfEven" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is halfEven (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "halfEven" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is halfEven (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "halfEven" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is halfEven (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "halfEven" }); +assert.sameValue(result7, "12:35", "roundingMode is halfEven (round to minute)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js new file mode 100644 index 0000000000..0cfb80098a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfExpand.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfExpand value for roundingMode option +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 (with 6 digits from smallestUnit)"); + +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: "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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfFloor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfFloor.js new file mode 100644 index 0000000000..e5edab5e8f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfFloor.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfFloor value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfFloor" }); +assert.sameValue(result1, "12:34:56.123987", + "roundingMode is halfFloor (with 6 digits from smallestUnit)"); + +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "halfFloor" }); +assert.sameValue(result2, "12:34:56.123987", + "roundingMode is halfFloor (with 6 digits from fractionalSecondDigits)"); + +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfFloor" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is halfFloor (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "halfFloor" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is halfFloor (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "halfFloor" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is halfFloor (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "halfFloor" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is halfFloor (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "halfFloor" }); +assert.sameValue(result7, "12:35", "roundingMode is halfFloor (round to minute)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfTrunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfTrunc.js new file mode 100644 index 0000000000..9c94a5d011 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-halfTrunc.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: halfTrunc value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const result1 = time.toString({ smallestUnit: "microsecond", roundingMode: "halfTrunc" }); +assert.sameValue(result1, "12:34:56.123987", + "roundingMode is halfTrunc (with 6 digits from smallestUnit)"); + +const result2 = time.toString({ fractionalSecondDigits: 6, roundingMode: "halfTrunc" }); +assert.sameValue(result2, "12:34:56.123987", + "roundingMode is halfTrunc (with 6 digits from fractionalSecondDigits)"); + +const result3 = time.toString({ smallestUnit: "millisecond", roundingMode: "halfTrunc" }); +assert.sameValue(result3, "12:34:56.124", + "roundingMode is halfTrunc (with 3 digits from smallestUnit)"); + +const result4 = time.toString({ fractionalSecondDigits: 3, roundingMode: "halfTrunc" }); +assert.sameValue(result4, "12:34:56.124", + "roundingMode is halfTrunc (with 3 digits from fractionalSecondDigits)"); + +const result5 = time.toString({ smallestUnit: "second", roundingMode: "halfTrunc" }); +assert.sameValue(result5, "12:34:56", + "roundingMode is halfTrunc (with 0 digits from smallestUnit)"); + +const result6 = time.toString({ fractionalSecondDigits: 0, roundingMode: "halfTrunc" }); +assert.sameValue(result6, "12:34:56", + "roundingMode is halfTrunc (with 0 digits from fractionalSecondDigits)"); + +const result7 = time.toString({ smallestUnit: "minute", roundingMode: "halfTrunc" }); +assert.sameValue(result7, "12:35", "roundingMode is halfTrunc (round to minute)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js new file mode 100644 index 0000000000..e59438a859 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => time.toString({ smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js new file mode 100644 index 0000000000..349ec756fc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-trunc.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: trunc value for roundingMode option +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 (with 6 digits from smallestUnit)"); + +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: "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)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js new file mode 100644 index 0000000000..836cbb0f68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for roundingMode option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const explicit1 = time.toString({ smallestUnit: "microsecond", roundingMode: undefined }); +assert.sameValue(explicit1, "12:34:56.123987", "default roundingMode is trunc"); +const implicit1 = time.toString({ smallestUnit: "microsecond" }); +assert.sameValue(implicit1, "12:34:56.123987", "default roundingMode is trunc"); + +const explicit2 = time.toString({ smallestUnit: "millisecond", roundingMode: undefined }); +assert.sameValue(explicit2, "12:34:56.123", "default roundingMode is trunc"); +const implicit2 = time.toString({ smallestUnit: "millisecond" }); +assert.sameValue(implicit2, "12:34:56.123", "default roundingMode is trunc"); + +const explicit3 = time.toString({ smallestUnit: "second", roundingMode: undefined }); +assert.sameValue(explicit3, "12:34:56", "default roundingMode is trunc"); +const implicit3 = time.toString({ smallestUnit: "second" }); +assert.sameValue(implicit3, "12:34:56", "default roundingMode is trunc"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js new file mode 100644 index 0000000000..2d7a86a9c0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => time.toString({ smallestUnit: "microsecond", roundingMode }), + (result, descr) => assert.sameValue(result, "12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js new file mode 100644 index 0000000000..9a9b87c3d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-fractionalseconddigits.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: fractionalSecondDigits option is not used with smallestUnit present +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const tests = [ + ["minute", "12:34"], + ["second", "12:34:56"], + ["millisecond", "12:34:56.789"], + ["microsecond", "12:34:56.789999"], + ["nanosecond", "12:34:56.789999999"], +]; + +for (const [smallestUnit, expected] of tests) { + const string = time.toString({ + smallestUnit, + fractionalSecondDigits: 5, + }); + assert.sameValue(string, expected, `smallestUnit: "${smallestUnit}" overrides fractionalSecondDigits`); +} + +assert.throws(RangeError, () => time.toString({ + smallestUnit: "hour", + fractionalSecondDigits: 5, +}), "hour is an invalid smallestUnit but still overrides fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js new file mode 100644 index 0000000000..7b31d12b17 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when smallestUnit option not one of the allowed string values +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js new file mode 100644 index 0000000000..9fde77c2c4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 789, 999, 999); +const validUnits = [ + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => time.toString({ smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js new file mode 100644 index 0000000000..fb45251a66 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tostring +description: Fallback value for smallestUnit option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); + +const explicit1 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 6 }); +assert.sameValue(explicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); +const implicit1 = time.toString({ fractionalSecondDigits: 6 }); +assert.sameValue(implicit1, "12:34:56.123987", "default smallestUnit defers to fractionalSecondDigits"); + +const explicit2 = time.toString({ smallestUnit: undefined, fractionalSecondDigits: 3 }); +assert.sameValue(explicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); +const implicit2 = time.toString({ fractionalSecondDigits: 3 }); +assert.sameValue(implicit2, "12:34:56.123", "default smallestUnit defers to fractionalSecondDigits"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js new file mode 100644 index 0000000000..6d44d85080 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Valid units for the smallestUnit option +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 456, 789); + +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", + "day", + "hour", +]; + +notValid.forEach((smallestUnit) => { + assert.throws(RangeError, () => time.toString({ smallestUnit }), + `"${smallestUnit}" is not a valid unit for the smallestUnit option`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js new file mode 100644 index 0000000000..33715d5b90 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type.js @@ -0,0 +1,18 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => time.toString({ smallestUnit }), + (result, descr) => assert.sameValue(result, "12:34:56.123987", descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/prop-desc.js new file mode 100644 index 0000000000..355fee5ac9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/prop-desc.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype-@@tostringtag +description: The @@toStringTag property of Temporal.PlainTime +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype, Symbol.toStringTag, { + value: "Temporal.PlainTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toStringTag/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-builtin-calendar-no-array-iteration.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-builtin-calendar-no-array-iteration.js new file mode 100644 index 0000000000..4aab6d8fcd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-builtin-calendar-no-array-iteration.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Calling the method with a property bag argument with a builtin calendar causes + no observable array iteration when getting the calendar fields. +features: [Temporal] +---*/ + +const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator]; +Array.prototype[Symbol.iterator] = function arrayIterator() { + throw new Test262Error("Array should not be iterated"); +} + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const arg = { year: 2000, month: 5, day: 2, calendar: "iso8601" }; +instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + +Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js new file mode 100644 index 0000000000..b24fe89cee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-calendar-datefromfields-called-with-null-prototype-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Calendar.dateFromFields method is called with a null-prototype fields object +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution(); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const arg = { year: 2000, month: 5, day: 2, calendar }; +instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-constructor-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-constructor-in-calendar-fields.js new file mode 100644 index 0000000000..df8e557c95 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-constructor-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-duplicate-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-duplicate-calendar-fields.js new file mode 100644 index 0000000000..c6b11b1c5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-duplicate-calendar-fields.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +for (const extra_fields of [['foo', 'foo'], ['day'], ['month'], ['monthCode'], ['year']]) { + const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields); + const arg = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar }; + const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + + assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-leap-second.js new file mode 100644 index 0000000000..4adfadacb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-leap-second.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Leap second is a valid ISO string for PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue( + result1.epochNanoseconds, + 1_483_187_696_987_654_321n, + "leap second is a valid ISO string for PlainDate" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue( + result2.epochNanoseconds, + 1_483_187_696_987_654_321n, + "second: 60 is ignored in property bag for PlainDate" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-number.js new file mode 100644 index 0000000000..a171ac85d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: A number cannot be used in place of a Temporal.PlainDate +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + 19761118, + -19761118, + 1234567890, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + 'Numbers cannot be used in place of an ISO string for PlainDate' + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js new file mode 100644 index 0000000000..db71724782 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-plaindatetime.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: Fast path for converting Temporal.PlainDateTime to Temporal.PlainDate by reading internal slots +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 5. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.b: + b. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then + i. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkPlainDateTimeConversionFastPath((datetime) => { + const time = new Temporal.PlainTime(6, 54, 32, 123, 456, 789); + const result = time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" }); + assert.sameValue(result.year, 2000, "year result"); + assert.sameValue(result.month, 5, "month result"); + assert.sameValue(result.day, 2, "day result"); + assert.sameValue(result.hour, 6, "hour result"); + assert.sameValue(result.minute, 54, "minute result"); + assert.sameValue(result.second, 32, "second result"); + assert.sameValue(result.millisecond, 123, "millisecond result"); + assert.sameValue(result.microsecond, 456, "microsecond result"); + assert.sameValue(result.nanosecond, 789, "nanosecond result"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js new file mode 100644 index 0000000000..71011392de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-primitive.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: TypeError thrown if a primitive is passed as the argument +info: | + Temporal.PlainTime.prototype.toZonedDateTime ( item ) + + 3. If Type(item) is not Object, then + a. Throw a TypeError exception. +features: [Symbol, Temporal] +---*/ + +const instance = Temporal.PlainTime.from("00:00"); + +assert.throws(TypeError, () => instance.toZonedDateTime(undefined), "undefined"); +assert.throws(TypeError, () => instance.toZonedDateTime(null), "null"); +assert.throws(TypeError, () => instance.toZonedDateTime(true), "true"); +assert.throws(TypeError, () => instance.toZonedDateTime(""), "empty string"); +assert.throws(TypeError, () => instance.toZonedDateTime(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.toZonedDateTime(1), "1"); +assert.throws(TypeError, () => instance.toZonedDateTime(1n), "1n"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-case-insensitive.js new file mode 100644 index 0000000000..476177705e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-case-insensitive.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: The calendar name is case-insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "IsO8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue(result.epochNanoseconds, 217_168_496_987_654_321n, "Calendar is case-insensitive"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-leap-second.js new file mode 100644 index 0000000000..126ebf0d1c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-leap-second.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Leap second is a valid ISO string for a calendar in a property bag +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "2016-12-31T23:59:60"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue( + result.epochNanoseconds, + 217_168_496_987_654_321n, + "leap second is a valid ISO string for calendar" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-number.js new file mode 100644 index 0000000000..d1ec94a514 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-number.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: A number as calendar in a property bag is not accepted +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + 19970327, + -19970327, + 1234567890, +]; + +for (const calendar of numbers) { + const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; + assert.throws( + TypeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + "Numbers cannot be used as a calendar" + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-string.js new file mode 100644 index 0000000000..11f185579a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-string.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: A calendar ID is valid input for Calendar +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const calendar = "iso8601"; + +const arg = { year: 1976, monthCode: "M11", day: 18, calendar }; +const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.sameValue(result.epochNanoseconds, 217_168_496_987_654_321n, `Calendar created from string "${calendar}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-wrong-type.js new file mode 100644 index 0000000000..fca5483d19 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-wrong-type.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Appropriate error thrown when a calendar property from a property bag cannot + be converted to a calendar object or string +features: [BigInt, Symbol, Temporal] +---*/ + +const timeZone = new Temporal.TimeZone("UTC"); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [calendar, description] of primitiveTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws( + typeof calendar === 'string' ? RangeError : TypeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object that doesn't implement the protocol"], + [new Temporal.TimeZone("UTC"), "time zone instance"], + [Temporal.Calendar, "Temporal.Calendar, object"], + [Temporal.Calendar.prototype, "Temporal.Calendar.prototype, object"], // fails brand check in dateFromFields() +]; + +for (const [calendar, description] of typeErrorTests) { + const arg = { year: 2019, monthCode: "M11", day: 1, calendar }; + assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-year-zero.js new file mode 100644 index 0000000000..2acf24b30d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-calendar-year-zero.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T17:45", + "-000000-10-31T17:45Z", + "-000000-10-31T17:45+01:00", + "-000000-10-31T17:45+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-missing-properties.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-missing-properties.js new file mode 100644 index 0000000000..e2aaab1a86 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-propertybag-missing-properties.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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.tozoneddatetime +description: Both plainDate and timeZone properties need to not be undefined. +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); +const plainDate = new Temporal.PlainDate(2022, 5, 19); +const timeZone = new Temporal.TimeZone("UTC"); +assert.throws(TypeError, () => instance.toZonedDateTime({}), + "no properties"); +assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate }), + "only plainDate"); +assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate, timeZone: undefined }), + "timeZone explicitly undefined"); +assert.throws(TypeError, () => instance.toZonedDateTime({ timeZone }), + "only timeZone"); +assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate: undefined, timeZone }), + "plainDate explicitly undefined"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-proto-in-calendar-fields.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-proto-in-calendar-fields.js new file mode 100644 index 0000000000..ace48b7cb0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-proto-in-calendar-fields.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']); +const arg = {year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar}; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..c48022d265 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-calendar-annotation.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["2000-05-02[u-ca=iso8601]", "without time or time zone"], + ["2000-05-02[UTC][u-ca=iso8601]", "with time zone and no time"], + ["2000-05-02T15:23[u-ca=iso8601]", "without time zone"], + ["2000-05-02T15:23[UTC][u-ca=iso8601]", "with time zone"], + ["2000-05-02T15:23[!u-ca=iso8601]", "with ! and no time zone"], + ["2000-05-02T15:23[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["2000-05-02T15:23[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + + assert.sameValue( + result.epochNanoseconds, + 957_270_896_987_654_321n, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..dc53b6ebfe --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-critical-unknown-annotation.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..fcc2b3f072 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-date-with-utc-offset.js @@ -0,0 +1,48 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: UTC offset not valid with format that does not include a time +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const validStrings = [ + "2000-05-02T00+00:00", + "2000-05-02T00+00:00[UTC]", + "2000-05-02T00+00:00[!UTC]", + "2000-05-02T00-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + + assert.sameValue( + result.epochNanoseconds, + 957_270_896_987_654_321n, + `"${arg}" is a valid UTC offset with time for PlainDate` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `"${arg}" UTC offset without time is not valid for PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js new file mode 100644 index 0000000000..1757339404 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-invalid.js @@ -0,0 +1,64 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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, timeZone: "UTC" }), + `"${arg}" should not be a valid ISO string for a PlainDate` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..d381bc0212 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..a95338db3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-multiple-time-zone.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "1970-01-01[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-separators.js new file mode 100644 index 0000000000..653debbd30 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-separators.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Time separator in string argument can vary +features: [Temporal] +---*/ + +const tests = [ + ["2000-05-02T15:23", "uppercase T"], + ["2000-05-02t15:23", "lowercase T"], + ["2000-05-02 15:23", "space between date and time"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + + assert.sameValue( + result.epochNanoseconds, + 957_270_896_987_654_321n, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..c49c5b85d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-time-zone-annotation.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +---*/ + +const tests = [ + ["2000-05-02[Asia/Kolkata]", "named, with no time"], + ["2000-05-02[!Europe/Vienna]", "named, with ! and no time"], + ["2000-05-02[+00:00]", "numeric, with no time"], + ["2000-05-02[!-02:30]", "numeric, with ! and no time"], + ["2000-05-02T15:23[America/Sao_Paulo]", "named, with no offset"], + ["2000-05-02T15:23[!Asia/Tokyo]", "named, with ! and no offset"], + ["2000-05-02T15:23[-02:30]", "numeric, with no offset"], + ["2000-05-02T15:23[!+00:00]", "numeric, with ! and no offset"], + ["2000-05-02T15:23+00:00[America/New_York]", "named, with offset"], + ["2000-05-02T15:23+00:00[!UTC]", "named, with offset and !"], + ["2000-05-02T15:23+00:00[+01:00]", "numeric, with offset"], + ["2000-05-02T15:23+00:00[!-08:00]", "numeric, with offset and !"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + + assert.sameValue( + result.epochNanoseconds, + 957_270_896_987_654_321n, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..b570aa57c5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-unknown-annotation.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Various forms of unknown annotation +features: [Temporal] +---*/ + +const tests = [ + ["2000-05-02[foo=bar]", "without time"], + ["2000-05-02T15:23[foo=bar]", "alone"], + ["2000-05-02T15:23[UTC][foo=bar]", "with time zone"], + ["2000-05-02T15:23[u-ca=iso8601][foo=bar]", "with calendar"], + ["2000-05-02T15:23[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["2000-05-02T15:23[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); + + assert.sameValue( + result.epochNanoseconds, + 957_270_896_987_654_321n, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..c36daff5df --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-string-with-utc-designator.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if a string with UTC designator is used as a PlainDate +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + "String with UTC designator should not be valid as a PlainDate" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-wrong-type.js new file mode 100644 index 0000000000..762fa6e9b9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainDate +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [undefined, "undefined"], // plainDate property is required + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainDate, "Temporal.PlainDate, object"], + [Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-convert.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-convert.js new file mode 100644 index 0000000000..43ccf45aec --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-convert.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: An exception from TimeZone#getOffsetNanosecondsFor() is propagated. +features: [Temporal] +---*/ + +class TZ extends Temporal.TimeZone { + constructor() { super("UTC") } + getOffsetNanosecondsFor() { throw new Test262Error() } +} + +const tz = new TZ(); +const arg = new Temporal.ZonedDateTime(0n, tz); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(Test262Error, () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-slots.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-slots.js new file mode 100644 index 0000000000..a8dea3776c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-slots.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Getters are not called when converting a ZonedDateTime to a PlainDate. +includes: [compareArray.js] +features: [Temporal] +---*/ + +const actual = []; +const prototypeDescrs = Object.getOwnPropertyDescriptors(Temporal.ZonedDateTime.prototype); +const getters = ["year", "month", "monthCode", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "calendar"]; + +for (const property of getters) { + Object.defineProperty(Temporal.ZonedDateTime.prototype, property, { + get() { + actual.push(`get ${property}`); + const value = prototypeDescrs[property].get.call(this); + return { + toString() { + actual.push(`toString ${property}`); + return value.toString(); + }, + valueOf() { + actual.push(`valueOf ${property}`); + return value; + }, + }; + }, + }); +} + +const arg = new Temporal.ZonedDateTime(0n, "UTC"); +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }); +assert.compareArray(actual, []); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..39ca85488e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..79284d6948 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..359fcb371c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..b1e0abaa25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.toZonedDateTime({ plainDate: datetime, timeZone: "UTC" })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js new file mode 100644 index 0000000000..8dd138b0eb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/basic.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.tozoneddatetime +description: Basic tests for toZonedDateTime(). +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from('12:00'); +const plainDate = Temporal.PlainDate.from('2020-07-08'); +const timeZone = Temporal.TimeZone.from('-07:00'); + +const objects = plainTime.toZonedDateTime({ timeZone, plainDate }); +assert.sameValue(objects.epochNanoseconds, 1594234800000000000n, "objects: epochNanoseconds"); +assert.sameValue(objects.getTimeZone(), timeZone, "objects: timeZone"); + +const timeZoneString = plainTime.toZonedDateTime({ timeZone: "-07:00", plainDate }); +assert.sameValue(timeZoneString.epochNanoseconds, 1594234800000000000n, "timeZone string: epochNanoseconds"); +assert.sameValue(timeZoneString.timeZoneId, "-07:00", "timeZone string: timeZone"); + +const plainDateString = plainTime.toZonedDateTime({ timeZone, plainDate: "2020-07-08" }); +assert.sameValue(plainDateString.epochNanoseconds, 1594234800000000000n, "plainDate string: epochNanoseconds"); +assert.sameValue(plainDateString.getTimeZone(), timeZone, "plainDate string: timeZone"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/branding.js new file mode 100644 index 0000000000..9df89a0dd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const toZonedDateTime = Temporal.PlainTime.prototype.toZonedDateTime; + +assert.sameValue(typeof toZonedDateTime, "function"); + +const args = [{ plainDate: "2022-05-19", timeZone: "UTC" }]; + +assert.throws(TypeError, () => toZonedDateTime.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => toZonedDateTime.apply(null, args), "null"); +assert.throws(TypeError, () => toZonedDateTime.apply(true, args), "true"); +assert.throws(TypeError, () => toZonedDateTime.apply("", args), "empty string"); +assert.throws(TypeError, () => toZonedDateTime.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => toZonedDateTime.apply(1, args), "1"); +assert.throws(TypeError, () => toZonedDateTime.apply({}, args), "plain object"); +assert.throws(TypeError, () => toZonedDateTime.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => toZonedDateTime.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js new file mode 100644 index 0000000000..e9271270ce --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Tests that Temporal.PlainTime.prototype.toZonedDateTime + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.toZonedDateTime), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.toZonedDateTime), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.toZonedDateTime), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.toZonedDateTime.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js new file mode 100644 index 0000000000..a94747cf81 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-datefromfields-called-with-options-undefined.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js new file mode 100644 index 0000000000..b8c58af599 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-fields-iterable.js @@ -0,0 +1,34 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Verify the result of calendar.fields() is treated correctly. +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 3. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »). + sec-temporal-calendarfields step 4: + 4. Let _result_ be ? IterableToList(_fieldsArray_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + "day", + "month", + "monthCode", + "year", +]; + +const time = new Temporal.PlainTime(13, 3); +const calendar = TemporalHelpers.calendarFieldsIterable(); +time.toZonedDateTime({ plainDate: { year: 2000, month: 5, day: 3, calendar }, timeZone: "UTC" }); + +assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once"); +assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args"); +assert(calendar.iteratorExhausted[0], "iterated through the whole iterable"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js new file mode 100644 index 0000000000..a9a98f20fd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/calendar-temporal-object.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 5: + 5. Let _temporalDate_ be ? ToTemporalDate(_temporalDateLike_). + sec-temporal-totemporaldate step 2.c: + c. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_). + sec-temporal-gettemporalcalendarwithisodefault step 2: + 2. Return ? ToTemporalCalendarWithISODefault(_calendar_). + sec-temporal-totemporalcalendarwithisodefault step 2: + 3. Return ? ToTemporalCalendar(_temporalCalendarLike_). + sec-temporal-totemporalcalendar step 1.a: + a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then + i. Return _temporalCalendarLike_.[[Calendar]]. +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject, calendar) => { + const time = new Temporal.PlainTime(13, 3); + const result = time.toZonedDateTime({ timeZone: "UTC", plainDate: { year: 2000, month: 5, day: 3, calendar: temporalObject } }); + assert.sameValue(result.getCalendar(), calendar, "Temporal object coerced to calendar"); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/getpossibleinstantsfor-called-with-iso8601-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/getpossibleinstantsfor-called-with-iso8601-calendar.js new file mode 100644 index 0000000000..729c58da0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/getpossibleinstantsfor-called-with-iso8601-calendar.js @@ -0,0 +1,58 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Time zone's getPossibleInstantsFor is called with a PlainDateTime with the + built-in ISO 8601 calendar +features: [Temporal] +info: | + DisambiguatePossibleInstants: + 2. Let _n_ be _possibleInstants_'s length. + ... + 5. Assert: _n_ = 0. + ... + 19. If _disambiguation_ is *"earlier"*, then + ... + c. Let _earlierDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*). + d. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _earlierDateTime_). + ... + 20. Assert: _disambiguation_ is *"compatible"* or *"later"*. + ... + 23. Let _laterDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*). + 24. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _laterDateTime_). +---*/ + +class SkippedDateTime extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.calls = 0; + } + + getPossibleInstantsFor(dateTime) { + // Calls occur in pairs. For the first one return no possible instants so + // that DisambiguatePossibleInstants will call it again + if (this.calls++ % 2 == 0) { + return []; + } + + assert.sameValue( + dateTime.getISOFields().calendar, + "iso8601", + "getPossibleInstantsFor called with dateTime with built-in ISO 8601 calendar" + ); + return super.getPossibleInstantsFor(dateTime); + } +} + +const nonBuiltinISOCalendar = new Temporal.Calendar("iso8601"); +const timeZone = new SkippedDateTime(); + +const instance = new Temporal.PlainTime(12, 34, 56); +instance.toZonedDateTime({ timeZone, plainDate: new Temporal.PlainDate(2000, 5, 2, nonBuiltinISOCalendar) }); + +assert.sameValue(timeZone.calls, 2, "getPossibleInstantsFor should have been called 2 times"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..56340351a6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.tozoneddatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js new file mode 100644 index 0000000000..73dda4c229 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Temporal.PlainTime.prototype.toZonedDateTime.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toZonedDateTime, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js new file mode 100644 index 0000000000..c6520773db --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Temporal.PlainTime.prototype.toZonedDateTime.name is "toZonedDateTime". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.toZonedDateTime, "name", { + value: "toZonedDateTime", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js new file mode 100644 index 0000000000..5e5068b867 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Temporal.PlainTime.prototype.toZonedDateTime does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.toZonedDateTime(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.toZonedDateTime), false, + "isConstructor(Temporal.PlainTime.prototype.toZonedDateTime)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/order-of-operations.js new file mode 100644 index 0000000000..168f4cf078 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/order-of-operations.js @@ -0,0 +1,118 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: User code calls happen in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const actual = []; +const expected = [ + "get item.plainDate", + "get item.plainDate.calendar", + "has item.plainDate.calendar.dateAdd", + "has item.plainDate.calendar.dateFromFields", + "has item.plainDate.calendar.dateUntil", + "has item.plainDate.calendar.day", + "has item.plainDate.calendar.dayOfWeek", + "has item.plainDate.calendar.dayOfYear", + "has item.plainDate.calendar.daysInMonth", + "has item.plainDate.calendar.daysInWeek", + "has item.plainDate.calendar.daysInYear", + "has item.plainDate.calendar.fields", + "has item.plainDate.calendar.id", + "has item.plainDate.calendar.inLeapYear", + "has item.plainDate.calendar.mergeFields", + "has item.plainDate.calendar.month", + "has item.plainDate.calendar.monthCode", + "has item.plainDate.calendar.monthDayFromFields", + "has item.plainDate.calendar.monthsInYear", + "has item.plainDate.calendar.weekOfYear", + "has item.plainDate.calendar.year", + "has item.plainDate.calendar.yearMonthFromFields", + "has item.plainDate.calendar.yearOfWeek", + "get item.plainDate.calendar.dateFromFields", + "get item.plainDate.calendar.fields", + "call item.plainDate.calendar.fields", + "get item.plainDate.day", + "get item.plainDate.day.valueOf", + "call item.plainDate.day.valueOf", + "get item.plainDate.month", + "get item.plainDate.month.valueOf", + "call item.plainDate.month.valueOf", + "get item.plainDate.monthCode", + "get item.plainDate.monthCode.toString", + "call item.plainDate.monthCode.toString", + "get item.plainDate.year", + "get item.plainDate.year.valueOf", + "call item.plainDate.year.valueOf", + "call item.plainDate.calendar.dateFromFields", + "get item.timeZone", + "has item.timeZone.getOffsetNanosecondsFor", + "has item.timeZone.getPossibleInstantsFor", + "has item.timeZone.id", + "get item.timeZone.getOffsetNanosecondsFor", + "get item.timeZone.getPossibleInstantsFor", + "call item.timeZone.getPossibleInstantsFor", +]; + +const calendar = TemporalHelpers.calendarObserver(actual, "item.plainDate.calendar"); +const instance = new Temporal.PlainTime(2, 30); + +const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone(); +const timeZone = TemporalHelpers.timeZoneObserver(actual, "item.timeZone", { + getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor, + getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor, +}); + +const plainDate = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 1, + monthCode: "M01", + day: 1, + calendar, +}, "item.plainDate"); +instance.toZonedDateTime(TemporalHelpers.propertyBagObserver(actual, { + plainDate, + timeZone, +}, "item")); +assert.compareArray(actual, expected, "order of operations at normal wall-clock time"); +actual.splice(0); // clear + +const fallBackPlainDate = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 10, + monthCode: "M10", + day: 29, + calendar, +}, "item.plainDate"); +const fallBackInstance = new Temporal.PlainTime(1, 30); +fallBackInstance.toZonedDateTime(TemporalHelpers.propertyBagObserver(actual, { + plainDate: fallBackPlainDate, + timeZone, +}, "item")); +assert.compareArray(actual, expected, "order of operations at repeated wall-clock time"); +actual.splice(0); // clear + +const springForwardPlainDate = TemporalHelpers.propertyBagObserver(actual, { + year: 2000, + month: 4, + monthCode: "M04", + day: 2, + calendar, +}, "item.plainDate"); +instance.toZonedDateTime(TemporalHelpers.propertyBagObserver(actual, { + plainDate: springForwardPlainDate, + timeZone, +}, "item")); +assert.compareArray(actual, expected.concat([ + "call item.timeZone.getOffsetNanosecondsFor", + "call item.timeZone.getOffsetNanosecondsFor", + "call item.timeZone.getPossibleInstantsFor", +]), "order of operations at skipped wall-clock time"); +actual.splice(0); // clear + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js new file mode 100644 index 0000000000..6df15bc12c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/plaindate-infinity-throws-rangeerror.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.tozoneddatetime +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(15); +const base = { year: 2000, month: 5, day: 2 }; + +[Infinity, -Infinity].forEach((inf) => { + ["year", "month", "day"].forEach((prop) => { + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in plainDate`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.toZonedDateTime({ timeZone: "UTC", plainDate: { ...base, [prop]: obj } })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js new file mode 100644 index 0000000000..354de10328 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: The "toZonedDateTime" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.toZonedDateTime, + "function", + "`typeof PlainTime.prototype.toZonedDateTime` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "toZonedDateTime", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-case-insensitive.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-case-insensitive.js new file mode 100644 index 0000000000..1c276cdc60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-case-insensitive.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Time zone names are case insensitive +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const timeZone = 'uTc'; +const result = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result.timeZoneId, 'UTC', `Time zone created from string "${timeZone}"`); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..ef8f207249 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..224ce6a5ed --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.toZonedDateTime({ plainDate, timeZone }), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..522e2c7b0b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + assert.throws(RangeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..aafa053af7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,31 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const plainDate = new Temporal.PlainDate(2000, 5, 2); + timeZone.getPossibleInstantsFor = function () { + return []; + }; + assert.throws(TypeError, () => time.toZonedDateTime({ plainDate, timeZone })); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..78c729ac0f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,45 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 10: + 10. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected1 = [ + "2000-05-02T12:34:56.987654321", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(0, 30); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2030, 1, 1), timeZone }); +}, expected2); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js new file mode 100644 index 0000000000..cce8691a13 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-datetime.js @@ -0,0 +1,65 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Conversion of ISO date-time strings to Temporal.TimeZone instances +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +let timeZone = "2021-08-19T17:30"; +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), "bare date-time string is not a time zone"); + +[ + "2021-08-19T17:30-07:00:01", + "2021-08-19T17:30-07:00:00", + "2021-08-19T17:30-07:00:00.1", + "2021-08-19T17:30-07:00:00.0", + "2021-08-19T17:30-07:00:00.01", + "2021-08-19T17:30-07:00:00.00", + "2021-08-19T17:30-07:00:00.001", + "2021-08-19T17:30-07:00:00.000", + "2021-08-19T17:30-07:00:00.0001", + "2021-08-19T17:30-07:00:00.0000", + "2021-08-19T17:30-07:00:00.00001", + "2021-08-19T17:30-07:00:00.00000", + "2021-08-19T17:30-07:00:00.000001", + "2021-08-19T17:30-07:00:00.000000", + "2021-08-19T17:30-07:00:00.0000001", + "2021-08-19T17:30-07:00:00.0000000", + "2021-08-19T17:30-07:00:00.00000001", + "2021-08-19T17:30-07:00:00.00000000", + "2021-08-19T17:30-07:00:00.000000001", + "2021-08-19T17:30-07:00:00.000000000", +].forEach((timeZone) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), + `ISO string ${timeZone} with a sub-minute offset is not a valid time zone` + ); +}); + +timeZone = "2021-08-19T17:30Z"; +const result1 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result1.timeZoneId, "UTC", "date-time + Z is UTC time zone"); + +timeZone = "2021-08-19T17:30-07:00"; +const result2 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result2.timeZoneId, "-07:00", "date-time + offset is the offset time zone"); + +timeZone = "2021-08-19T17:30[UTC]"; +const result3 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result3.timeZoneId, "UTC", "date-time + IANA annotation is the IANA time zone"); + +timeZone = "2021-08-19T17:30Z[UTC]"; +const result4 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result4.timeZoneId, "UTC", "date-time + Z + IANA annotation is the IANA time zone"); + +timeZone = "2021-08-19T17:30-07:00[UTC]"; +const result5 = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result5.timeZoneId, "UTC", "date-time + offset + IANA annotation is the IANA time zone"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-leap-second.js new file mode 100644 index 0000000000..b9ffeaf896 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-leap-second.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Leap second is a valid ISO string for TimeZone +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); +let timeZone = "2016-12-31T23:59:60+00:00[UTC]"; + +const result = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result.timeZoneId, "UTC", "leap second is a valid ISO string for TimeZone"); + +timeZone = "2021-08-19T17:30:45.123456789+23:59[+23:59:60]"; +assert.throws(RangeError, () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), "leap second in time zone name not valid"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js new file mode 100644 index 0000000000..7891dfd8b0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-multiple-offsets.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Time zone parsing from ISO strings uses the bracketed offset, not the ISO string offset +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); +const timeZone = "2021-08-19T17:30:45.123456789-12:12[+01:46]"; + +const result = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +assert.sameValue(result.timeZoneId, "+01:46", "Time zone string determined from bracket name"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-year-zero.js new file mode 100644 index 0000000000..e89a158fab --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string-year-zero.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31T17:45Z", + "-000000-10-31T17:45+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(); +invalidStrings.forEach((timeZone) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string.js new file mode 100644 index 0000000000..1dfee59178 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-string.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Time zone IDs are valid input for a time zone +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const getPossibleInstantsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getPossibleInstantsFor"); +Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", { + configurable: true, + enumerable: false, + get() { + TemporalHelpers.assertUnreachable("getPossibleInstantsFor should not be looked up"); + }, +}); +const getOffsetNanosecondsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor"); +Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", { + configurable: true, + enumerable: false, + get() { + TemporalHelpers.assertUnreachable("getOffsetNanosecondsFor should not be looked up"); + }, +}); + +const instance = new Temporal.PlainTime(); + +["UTC", "+01:30"].forEach((timeZone) => { + const result = instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); + assert.sameValue(result.getISOFields().timeZone, timeZone, `time zone slot should store string "${timeZone}"`); +}); + +Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", getPossibleInstantsForOriginal); +Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", getOffsetNanosecondsForOriginal); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-wrong-type.js new file mode 100644 index 0000000000..8dbf4e45dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/timezone-wrong-type.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or object for TimeZone +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const primitiveTests = [ + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [19761118, "number that would convert to a valid ISO string in other contexts"], + [1n, "bigint"], +]; + +for (const [timeZone, description] of primitiveTests) { + assert.throws( + typeof timeZone === 'string' ? RangeError : TypeError, + () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "object not implementing time zone protocol"], + [new Temporal.Calendar("iso8601"), "calendar instance"], +]; + +for (const [timeZone, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }), `${description} is not a valid object and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js new file mode 100644 index 0000000000..fd73928276 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/toZonedDateTime/year-zero.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +description: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-10-31", + "-000000-10-31T00:45", + "-000000-10-31T00:45+01:00", + "-000000-10-31T00:45+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.toZonedDateTime({ plainDate: arg, timeZone: "UTC" }), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js new file mode 100644 index 0000000000..8fae64634f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-cast.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Casts the argument +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertDuration(plainTime.until("16:34"), + 0, 0, 0, 0, /* hours = */ 1, /* minutes = */ 10, /* seconds = */ 29, 876, 543, 211, "string"); +TemporalHelpers.assertDuration(plainTime.until({ hour: 16, minute: 34 }), + 0, 0, 0, 0, /* hours = */ 1, /* minutes = */ 10, /* seconds = */ 29, 876, 543, 211, "object"); + +assert.throws(TypeError, () => plainTime.until({}), "empty"); +assert.throws(TypeError, () => plainTime.until({ minutes: 30 }), "only plural 'minutes'"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-number.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-number.js new file mode 100644 index 0000000000..184cc6609e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-number.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: A number is invalid in place of an ISO string for Temporal.PlainTime +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const numbers = [ + 1, + -123456.987654321, + 1234567, + 123456.9876543219, +]; + +for (const arg of numbers) { + assert.throws( + TypeError, + () => instance.until(arg), + `A number (${arg}) is not a valid ISO string for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-calendar-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-calendar-annotation.js new file mode 100644 index 0000000000..5131007c25 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-calendar-annotation.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Various forms of calendar annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[u-ca=iso8601]", "without time zone"], + ["12:34:56.987654321[UTC][u-ca=iso8601]", "with time zone"], + ["12:34:56.987654321[!u-ca=iso8601]", "with ! and no time zone"], + ["12:34:56.987654321[UTC][!u-ca=iso8601]", "with ! and time zone"], + ["T12:34:56.987654321[u-ca=iso8601]", "with T and no time zone"], + ["T12:34:56.987654321[UTC][u-ca=iso8601]", "with T and time zone"], + ["T12:34:56.987654321[!u-ca=iso8601]", "with T, !, and no time zone"], + ["T12:34:56.987654321[UTC][!u-ca=iso8601]", "with T, !, and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601]", "with date and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][u-ca=iso8601]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[!u-ca=iso8601]", "with !, date, and no time zone"], + ["1970-01-01T12:34:56.987654321[UTC][!u-ca=iso8601]", "with !, date, and time zone"], + ["12:34:56.987654321[u-ca=hebrew]", "calendar annotation ignored"], + ["12:34:56.987654321[u-ca=unknown]", "calendar annotation ignored even if unknown calendar"], + ["12:34:56.987654321[!u-ca=unknown]", "calendar annotation ignored even if unknown calendar with !"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][u-ca=discord]", "second annotation ignored"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `calendar annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-critical-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-critical-unknown-annotation.js new file mode 100644 index 0000000000..8f5566b2a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-critical-unknown-annotation.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Unknown annotations with critical flag are rejected +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[!foo=bar]", + "T00:00[!foo=bar]", + "1970-01-01T00:00[!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar]", + "1970-01-01T00:00[u-ca=iso8601][!foo=bar]", + "1970-01-01T00:00[UTC][!foo=bar][u-ca=iso8601]", + "1970-01-01T00:00[foo=bar][!_foo-bar0=Dont-Ignore-This-99999999999]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject unknown annotation with critical flag: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-date-with-utc-offset.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-date-with-utc-offset.js new file mode 100644 index 0000000000..1fbc1405b8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-date-with-utc-offset.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: UTC offset not valid with format that does not include a time +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const validStrings = [ + "12:34:56.987654321+00:00", + "12:34:56.987654321+00:00[UTC]", + "12:34:56.987654321+00:00[!UTC]", + "12:34:56.987654321-02:30[America/St_Johns]", + "1976-11-18T12:34:56.987654321+00:00", + "1976-11-18T12:34:56.987654321+00:00[UTC]", + "1976-11-18T12:34:56.987654321+00:00[!UTC]", + "1976-11-18T12:34:56.987654321-02:30[America/St_Johns]", +]; + +for (const arg of validStrings) { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `"${arg}" is a valid UTC offset with time for PlainTime` + ); +} + +const invalidStrings = [ + "2022-09-15Z", + "2022-09-15Z[UTC]", + "2022-09-15Z[Europe/Vienna]", + "2022-09-15+00:00", + "2022-09-15+00:00[UTC]", + "2022-09-15-02:30", + "2022-09-15-02:30[America/St_Johns]", +]; + +for (const arg of invalidStrings) { + assert.throws( + RangeError, + () => instance.until(arg), + `"${arg}" UTC offset without time is not valid for PlainTime` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-calendar.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-calendar.js new file mode 100644 index 0000000000..60669f4cb5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-calendar.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + More than one calendar annotation is not syntactical if any have the criical + flag +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[u-ca=iso8601][!u-ca=iso8601]", + "00:00[!u-ca=iso8601][u-ca=iso8601]", + "00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[!u-ca=iso8601][u-ca=iso8601]", + "1970-01-01T00:00[UTC][u-ca=iso8601][!u-ca=iso8601]", + "1970-01-01T00:00[u-ca=iso8601][foo=bar][!u-ca=iso8601]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject more than one calendar annotation if any critical: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-time-zone.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-time-zone.js new file mode 100644 index 0000000000..d98c81ecf6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-multiple-time-zone.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: More than one time zone annotation is not syntactical +features: [Temporal] +---*/ + +const invalidStrings = [ + "00:00[UTC][UTC]", + "T00:00[UTC][UTC]", + "1970-01-01T00:00[UTC][UTC]", + "1970-01-01T00:00[!UTC][UTC]", + "1970-01-01T00:00[UTC][!UTC]", + "1970-01-01T00:00[UTC][u-ca=iso8601][UTC]", + "1970-01-01T00:00[UTC][foo=bar][UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + `reject more than one time zone annotation: ${arg}` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js new file mode 100644 index 0000000000..6d0b98e8e5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-no-implicit-midnight.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if a date-only string is passed in a PlainTime context +features: [Temporal, arrow-function] +---*/ + +const arg = "2019-10-01"; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +assert.throws( + RangeError, + () => instance.until(arg), + "Date-only string throws, does not implicitly convert to midnight" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js new file mode 100644 index 0000000000..4c73919116 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-designator-required-for-disambiguation.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: ISO 8601 time designator "T" required in cases of ambiguity +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +TemporalHelpers.ISO.plainTimeStringsAmbiguous().forEach((string) => { + let arg = string; + assert.throws( + RangeError, + () => instance.until(arg), + `'${arg}' is ambiguous and requires T prefix` + ); + // The same string with a T prefix should not throw: + arg = `T${string}`; + instance.until(arg); + + arg = ` ${string}`; + assert.throws( + RangeError, + () => instance.until(arg), + `space is not accepted as a substitute for T prefix: '${arg}'` + ); +}); + +// None of these should throw without a T prefix, because they are unambiguously time strings: +TemporalHelpers.ISO.plainTimeStringsUnambiguous().forEach( + (arg) => instance.until(arg)); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-separators.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-separators.js new file mode 100644 index 0000000000..176b7c51a8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-separators.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Time separator in string argument can vary +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["1976-11-18T12:34:56.987654321", "uppercase T"], + ["1976-11-18t12:34:56.987654321", "lowercase T"], + ["1976-11-18 12:34:56.987654321", "space between date and time"], + ["T12:34:56.987654321", "time-only uppercase T"], + ["t12:34:56.987654321", "time-only lowercase T"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `variant time separators (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-zone-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-zone-annotation.js new file mode 100644 index 0000000000..7f01564d22 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-time-zone-annotation.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Various forms of time zone annotation; critical flag has no effect +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[Asia/Kolkata]", "named, with no offset"], + ["12:34:56.987654321[!Europe/Vienna]", "named, with ! and no offset"], + ["12:34:56.987654321[+00:00]", "numeric, with no offset"], + ["12:34:56.987654321[!-02:30]", "numeric, with ! and no offset"], + ["T12:34:56.987654321[UTC]", "named, with T and no offset"], + ["T12:34:56.987654321[!Africa/Abidjan]", "named, with T, !, and no offset"], + ["T12:34:56.987654321[+01:00]", "numeric, with T and no offset"], + ["T12:34:56.987654321[!-08:00]", "numeric, with T, !, and no offset"], + ["12:34:56.987654321+00:00[America/Sao_Paulo]", "named, with offset"], + ["12:34:56.987654321+00:00[!Asia/Tokyo]", "named, with ! and offset"], + ["12:34:56.987654321+00:00[-02:30]", "numeric, with offset"], + ["12:34:56.987654321+00:00[!+00:00]", "numeric, with ! and offset"], + ["T12:34:56.987654321+00:00[America/New_York]", "named, with T and offset"], + ["T12:34:56.987654321+00:00[!UTC]", "named, with T, !, and offset"], + ["T12:34:56.987654321+00:00[-08:00]", "numeric, with T and offset"], + ["T12:34:56.987654321+00:00[!+01:00]", "numeric, with T, !, and offset"], + ["1970-01-01T12:34:56.987654321[Africa/Lagos]", "named, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!America/Vancouver]", "named, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321[+00:00]", "numeric, with date and no offset"], + ["1970-01-01T12:34:56.987654321[!-02:30]", "numeric, with date, !, and no offset"], + ["1970-01-01T12:34:56.987654321+00:00[Europe/London]", "named, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!Asia/Seoul]", "named, with date, offset, and !"], + ["1970-01-01T12:34:56.987654321+00:00[+01:00]", "numeric, with date and offset"], + ["1970-01-01T12:34:56.987654321+00:00[!-08:00]", "numeric, with date, offset, and !"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `time zone annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-unknown-annotation.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-unknown-annotation.js new file mode 100644 index 0000000000..7cac3ea843 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-unknown-annotation.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Various forms of unknown annotation +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const tests = [ + ["12:34:56.987654321[foo=bar]", "alone"], + ["12:34:56.987654321[UTC][foo=bar]", "with time zone"], + ["12:34:56.987654321[u-ca=iso8601][foo=bar]", "with calendar"], + ["12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with time zone and calendar"], + ["T12:34:56.987654321[foo=bar]", "with T"], + ["T12:34:56.987654321[UTC][foo=bar]", "with T and time zone"], + ["T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with T and calendar"], + ["T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with T, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar]", "with date"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar]", "with date and time zone"], + ["1970-01-01T12:34:56.987654321[u-ca=iso8601][foo=bar]", "with date and calendar"], + ["1970-01-01T12:34:56.987654321[UTC][foo=bar][u-ca=iso8601]", "with date, time zone, and calendar"], + ["1970-01-01T12:34:56.987654321[foo=bar][_foo-bar0=Ignore-This-999999999999]", "with another unknown annotation"], +]; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +tests.forEach(([arg, description]) => { + const result = instance.until(arg); + + TemporalHelpers.assertDuration( + result, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + `unknown annotation (${description})` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js new file mode 100644 index 0000000000..1e481da34d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-time-designator.js @@ -0,0 +1,32 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: ISO 8601 time designator "T" allowed at the start of PlainTime strings +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); +const validStrings = [ + "T00:30", + "t00:30", + "T0030", + "t0030", + "T00:30:00", + "t00:30:00", + "T003000", + "t003000", + "T00:30:00.000000000", + "t00:30:00.000000000", + "T003000.000000000", + "t003000.000000000", +]; +validStrings.forEach((arg) => { + const result = instance.until(arg); + TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, -30, 0, 0, 0, -1, `T prefix is accepted: ${arg}`); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js new file mode 100644 index 0000000000..562616ef60 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-string-with-utc-designator.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if a string with UTC designator is used as a PlainTime +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "2019-10-01T09:00:00Z", + "2019-10-01T09:00:00Z[UTC]", + "09:00:00Z[UTC]", + "09:00:00Z", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "String with UTC designator should not be valid as a PlainTime" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-wrong-type.js new file mode 100644 index 0000000000..b585ea57c8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-wrong-type.js @@ -0,0 +1,43 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + Appropriate error thrown when argument cannot be converted to a valid string + or property bag for PlainTime +features: [BigInt, Symbol, Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const primitiveTests = [ + [undefined, "undefined"], + [null, "null"], + [true, "boolean"], + ["", "empty string"], + [1, "number that doesn't convert to a valid ISO string"], + [1n, "bigint"], +]; + +for (const [arg, description] of primitiveTests) { + assert.throws( + typeof arg === 'string' ? RangeError : TypeError, + () => instance.until(arg), + `${description} does not convert to a valid ISO string` + ); +} + +const typeErrorTests = [ + [Symbol(), "symbol"], + [{}, "plain object"], + [Temporal.PlainTime, "Temporal.PlainTime, object"], + [Temporal.PlainTime.prototype, "Temporal.PlainTime.prototype, object"], +]; + +for (const [arg, description] of typeErrorTests) { + assert.throws(TypeError, () => instance.until(arg), `${description} is not a valid property bag and does not convert to a string`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js new file mode 100644 index 0000000000..efb80edab9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-balance-negative-time-units.js @@ -0,0 +1,46 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Negative time fields are balanced upwards if the argument is given as ZonedDateTime +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-balanceisodatetime step 1: + 1. Let _balancedTime_ be ? BalanceTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_). + sec-temporal-builtintimezonegetplaindatetimefor step 3: + 3. Set _result_ to ? BalanceISODateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]] + _offsetNanoseconds_). + sec-temporal-totemporaltime step 3.b: + b. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + ... + ii. 1. Set _plainDateTime_ to ? BuiltinTimeZoneGetPlainDateTimeFor(_item_.[[TimeZone]], _instant_, _item_.[[Calendar]]). + sec-temporal.plaintime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalTime(_other_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +// This code path is encountered if the time zone offset is negative and its +// absolute value in nanoseconds is greater than the nanosecond field of the +// exact time's epoch parts +const tz = TemporalHelpers.specificOffsetTimeZone(-2); +const datetime = new Temporal.ZonedDateTime(3661_001_001_001n, tz); + +const diff = new Temporal.PlainTime().until(datetime); + +TemporalHelpers.assertDuration(diff, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js new file mode 100644 index 0000000000..f9d9b3ad92 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch +info: | + sec-temporal-getisopartsfromepoch step 1: + 1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>. + sec-temporal-builtintimezonegetplaindatetimefor step 2: + 2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]). +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +const datetime = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC"); + +// This code path shows up anywhere we convert an exact time, before the Unix +// epoch, with nonzero microseconds or nanoseconds, into a wall time. + +const instance = new Temporal.PlainTime(15); +const result = instance.until(datetime); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 50, 35, 0, 0, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js new file mode 100644 index 0000000000..244af3a92d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-non-integer.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js new file mode 100644 index 0000000000..14523f2df6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-not-callable.js @@ -0,0 +1,23 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable +features: [BigInt, Symbol, Temporal, arrow-function] +---*/ + +[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => { + const timeZone = new Temporal.TimeZone("UTC"); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + timeZone.getOffsetNanosecondsFor = notCallable; + assert.throws( + TypeError, + () => time.until(datetime), + `Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js new file mode 100644 index 0000000000..65a1b4997c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-out-of-range.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown if time zone reports an offset that is out of range +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(RangeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js new file mode 100644 index 0000000000..03a61ee229 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/argument-zoneddatetime-timezone-getoffsetnanosecondsfor-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown if time zone reports an offset that is not a Number +features: [Temporal] +includes: [temporalHelpers.js] +---*/ + +[ + undefined, + null, + true, + "+01:00", + Symbol(), + 3600_000_000_000n, + {}, + { valueOf() { return 3600_000_000_000; } }, +].forEach((wrongOffset) => { + const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset); + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + const datetime = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone); + assert.throws(TypeError, () => time.until(datetime)); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js new file mode 100644 index 0000000000..6dc665fbc0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/balance-negative-time-units.js @@ -0,0 +1,51 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Negative time fields are balanced upwards +info: | + sec-temporal-balancetime steps 3–14: + 3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000). + 4. Set _nanosecond_ to _nanosecond_ modulo 1000. + 5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000). + 6. Set _microsecond_ to _microsecond_ modulo 1000. + 7. Set _second_ to _second_ + floor(_millisecond_ / 1000). + 8. Set _millisecond_ to _millisecond_ modulo 1000. + 9. Set _minute_ to _minute_ + floor(_second_ / 60). + 10. Set _second_ to _second_ modulo 60. + 11. Set _hour_ to _hour_ + floor(_minute_ / 60). + 12. Set _minute_ to _minute_ modulo 60. + 13. Let _days_ be floor(_hour_ / 24). + 14. Set _hour_ to _hour_ modulo 24. + sec-temporal-differencetime step 8: + 8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + sec-temporal.plaintime.prototype.until step 11: + 11. Let _result_ be ! DifferenceTime(_temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]]). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(1, 1, 1, 1, 1, 1); + +const result1 = new Temporal.PlainTime(0, 0, 0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance"); + +const result2 = new Temporal.PlainTime(0, 0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance"); + +const result3 = new Temporal.PlainTime(0, 0, 0, 2).until(time); +TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance"); + +const result4 = new Temporal.PlainTime(0, 0, 2).until(time); +TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance"); + +const result5 = new Temporal.PlainTime(0, 2).until(time); +TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance"); + +// This one is different because hours are later balanced again in BalanceDuration +const result6 = new Temporal.PlainTime(2).until(time); +TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js new file mode 100644 index 0000000000..525652c204 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/basic.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Basic usage +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const one = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const two = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); +const three = new Temporal.PlainTime(17, 0, 30, 123, 456, 789); + +TemporalHelpers.assertDuration(one.until(two), + 0, 0, 0, 0, /* hours = */ 1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(two.until(one), + 0, 0, 0, 0, /* hours = */ -1, 0, 0, 0, 0, 0); +TemporalHelpers.assertDuration(one.until(three), + 0, 0, 0, 0, /* hours = */ 1, 37, 0, 0, 0, 0); +TemporalHelpers.assertDuration(three.until(one), + 0, 0, 0, 0, /* hours = */ -1, -37, 0, 0, 0, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/branding.js new file mode 100644 index 0000000000..58e1b3fa75 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const until = Temporal.PlainTime.prototype.until; + +assert.sameValue(typeof until, "function"); + +const args = [new Temporal.PlainTime(12)]; + +assert.throws(TypeError, () => until.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => until.apply(null, args), "null"); +assert.throws(TypeError, () => until.apply(true, args), "true"); +assert.throws(TypeError, () => until.apply("", args), "empty string"); +assert.throws(TypeError, () => until.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => until.apply(1, args), "1"); +assert.throws(TypeError, () => until.apply({}, args), "plain object"); +assert.throws(TypeError, () => until.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => until.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js new file mode 100644 index 0000000000..d0e21624e8 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + Tests that Temporal.PlainTime.prototype.until + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.until), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.until), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.until), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.until.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js new file mode 100644 index 0000000000..0284618463 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-invalid-string.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when largestUnit option not one of the allowed string values +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 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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js new file mode 100644 index 0000000000..4cd50f0195 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Plural units are accepted as well for the largestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((largestUnit) => earlier.until(later, { largestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js new file mode 100644 index 0000000000..2dd6528a00 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-smallestunit-mismatch.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when smallestUnit is larger than largestUnit +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 units = ["hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]; +for (let largestIdx = 1; largestIdx < units.length; largestIdx++) { + for (let smallestIdx = 0; smallestIdx < largestIdx; smallestIdx++) { + const largestUnit = units[largestIdx]; + const smallestUnit = units[smallestIdx]; + assert.throws(RangeError, () => earlier.until(later, { largestUnit, smallestUnit })); + } +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js new file mode 100644 index 0000000000..07a593980f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for largestUnit option +includes: [temporalHelpers.js] +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 explicit = earlier.until(later, { largestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default largestUnit is hour"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js new file mode 100644 index 0000000000..a685d4cd0a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for largestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("largestUnit", "second", + (largestUnit) => earlier.until(later, { largestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 3661, 987, 654, 321, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js new file mode 100644 index 0000000000..3f84e1be5a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/largestunit.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: PlainTime.until with various largestUnit values. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ +const fourFortyEight = new Temporal.PlainTime(4, 48, 55); +const elevenFiftyNine = new Temporal.PlainTime(11, 59, 58); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit unspecified)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "auto" }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is auto)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "hours" }), 0, 0, 0, 0, 7, 11, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is hours)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "minutes" }), 0, 0, 0, 0, 0, 431, 3, 0, 0, 0, "does not include higher units than necessary (largest unit is minutes)"); +TemporalHelpers.assertDuration(fourFortyEight.until(elevenFiftyNine, { largestUnit: "seconds" }), 0, 0, 0, 0, 0, 0, 25863, 0, 0, 0, "does not include higher units than necessary (largest unit is seconds)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/leap-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/leap-second.js new file mode 100644 index 0000000000..a3397d4d39 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/leap-second.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Leap second is a valid ISO string for PlainTime +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(23, 59, 59); + +let arg = "2016-12-31T23:59:60"; +const result1 = instance.until(arg); +TemporalHelpers.assertDuration( + result1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "leap second is a valid ISO string for PlainTime" +); + +arg = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 }; +const result2 = instance.until(arg); +TemporalHelpers.assertDuration( + result2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "second: 60 is ignored in property bag for PlainTime" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js new file mode 100644 index 0000000000..ebb5736dfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Temporal.PlainTime.prototype.until.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.until, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js new file mode 100644 index 0000000000..603d27dcac --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Temporal.PlainTime.prototype.until.name is "until". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.until, "name", { + value: "until", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js new file mode 100644 index 0000000000..5b4e7dcc2f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: > + Temporal.PlainTime.prototype.until does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.until(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.until), false, + "isConstructor(Temporal.PlainTime.prototype.until)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js new file mode 100644 index 0000000000..2340eefee9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-invalid.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: TypeError thrown when a primitive is passed as the options argument +features: [Temporal] +---*/ + +const values = [null, true, "hello", Symbol("foo"), 1, 1n]; +const time = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +const one = new Temporal.PlainTime(16, 23, 30, 123, 456, 789); + +for (const badOptions of values) { + assert.throws(TypeError, () => time.until(one, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-object.js new file mode 100644 index 0000000000..25cc69bca1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-object.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const result1 = instance.until(new Temporal.PlainTime(12, 34, 56), {}); +TemporalHelpers.assertDuration( + result1, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, + "options may be an empty plain object" +); + +const result2 = instance.until(new Temporal.PlainTime(12, 34, 56), () => {}); +TemporalHelpers.assertDuration( + result2, 0, 0, 0, 0, 12, 34, 56, 0, 0, 0, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js new file mode 100644 index 0000000000..c7f622e77a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(18, 34, 56, 987, 654, 322); + +const explicit = earlier.until(later, undefined); +assert.sameValue(explicit.hours, 6, "default largest unit is hours"); +assert.sameValue(explicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +const implicit = earlier.until(later); +assert.sameValue(implicit.hours, 6, "default largest unit is hours"); +assert.sameValue(implicit.nanoseconds, 1, "default smallest unit is nanoseconds and no rounding"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js new file mode 100644 index 0000000000..6706e49ba3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/order-of-operations.js new file mode 100644 index 0000000000..35a10fcd59 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/order-of-operations.js @@ -0,0 +1,95 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Properties on an object passed to until() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const expected = [ + // ToTemporalTime + "get other.hour", + "get other.hour.valueOf", + "call other.hour.valueOf", + "get other.microsecond", + "get other.microsecond.valueOf", + "call other.microsecond.valueOf", + "get other.millisecond", + "get other.millisecond.valueOf", + "call other.millisecond.valueOf", + "get other.minute", + "get other.minute.valueOf", + "call other.minute.valueOf", + "get other.nanosecond", + "get other.nanosecond.valueOf", + "call other.nanosecond.valueOf", + "get other.second", + "get other.second.valueOf", + "call other.second.valueOf", + // CopyDataProperties + "ownKeys options", + "getOwnPropertyDescriptor options.roundingIncrement", + "get options.roundingIncrement", + "getOwnPropertyDescriptor options.roundingMode", + "get options.roundingMode", + "getOwnPropertyDescriptor options.largestUnit", + "get options.largestUnit", + "getOwnPropertyDescriptor options.smallestUnit", + "get options.smallestUnit", + "getOwnPropertyDescriptor options.additional", + "get options.additional", + // GetDifferenceSettings + "get options.largestUnit.toString", + "call options.largestUnit.toString", + "get options.roundingIncrement.valueOf", + "call options.roundingIncrement.valueOf", + "get options.roundingMode.toString", + "call options.roundingMode.toString", + "get options.smallestUnit.toString", + "call options.smallestUnit.toString", +]; +const actual = []; + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const other = TemporalHelpers.propertyBagObserver(actual, { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, + calendar: "iso8601", +}, "other"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + roundingIncrement: 1, + roundingMode: "trunc", + largestUnit: "hours", + smallestUnit: "nanoseconds", + additional: true, +}, "options"); + +const result = instance.until(other, options); +assert.compareArray(actual, expected, "order of operations"); + +actual.splice(0); // clear + +// short-circuit does not skip reading options +const identicalPropertyBag = TemporalHelpers.propertyBagObserver(actual, { + hour: 12, + minute: 34, + second: 56, + millisecond: 987, + microsecond: 654, + nanosecond: 321, +}, "other"); +instance.until(identicalPropertyBag, options); +assert.compareArray(actual, expected, "order of operations with identical times"); + +actual.splice(0); // clear + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/plaintime-propertybag-no-time-units.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/plaintime-propertybag-no-time-units.js new file mode 100644 index 0000000000..2197e3a558 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/plaintime-propertybag-no-time-units.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Missing time units in property bag default to 0 +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(1, 0, 0, 0, 0, 1); + +const props = {}; +assert.throws(TypeError, () => instance.until(props), "TypeError if no properties are present"); + +props.minute = 30; +const result = instance.until(props); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, -30, 0, 0, 0, -1, "missing time units default to 0"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js new file mode 100644 index 0000000000..6c8038cdcd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: The "until" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.until, + "function", + "`typeof PlainTime.prototype.until` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "until", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js new file mode 100644 index 0000000000..52fdbde50f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/result-sub-second.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Supports sub-second precision +includes: [temporalHelpers.js] +features: [Temporal, arrow-function] +---*/ + +const time1 = Temporal.PlainTime.from("10:23:15"); +const time2 = Temporal.PlainTime.from("17:15:57.250250250"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "milliseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 24762250, 250, 250, "milliseconds"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "microseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 24762250250, 250, "microseconds"); + +TemporalHelpers.assertDuration(time1.until(time2, { largestUnit: "nanoseconds" }), + 0, 0, 0, 0, 0, 0, 0, /* milliseconds = */ 0, 0, 24762250250250, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/round-cross-unit-boundary.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/round-cross-unit-boundary.js new file mode 100644 index 0000000000..faef88b1dc --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/round-cross-unit-boundary.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2023 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Rounding can cross unit boundaries up to largestUnit +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(); +const later = new Temporal.PlainTime(1, 59, 59); +const duration = earlier.until(later, { largestUnit: "hours", smallestUnit: "minutes", roundingMode: "expand" }); +TemporalHelpers.assertDuration(duration, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, "1:60 balances to 2 hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js new file mode 100644 index 0000000000..01ed2f19bd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-hours.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 3 }), + 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 4 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 6 }), + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 8 }), + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingIncrement: 12 }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "hours"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js new file mode 100644 index 0000000000..4037f566ca --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-invalid.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests roundingIncrement restrictions. +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "hours", roundingIncrement: 11 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 29 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "hours", roundingIncrement: 24 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 60 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 60 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 1000 })); +assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 1000 })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js new file mode 100644 index 0000000000..3ae7e1aea5 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-microseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 196, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 195, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 192, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 190, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 180, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 175, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 160, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 150, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 100, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 125, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "microseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js new file mode 100644 index 0000000000..d24a0b8acf --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-milliseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 860, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 840, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 850, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 800, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 750, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 500, 0, 0, "milliseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js new file mode 100644 index 0000000000..5f98541718 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-minutes.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 34, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 33, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 32, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 24, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 20, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 30, 0, 0, 0, 0, "minutes"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js new file mode 100644 index 0000000000..5da9205585 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nan.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingIncrement option is NaN +info: | + sec-getoption step 8.b: + b. If _value_ is *NaN*, throw a *RangeError* exception. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: NaN })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js new file mode 100644 index 0000000000..59c55f6b84 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-nanoseconds.js @@ -0,0 +1,61 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 533, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 8 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 528, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 530, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 25 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 525, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 40 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 520, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 50 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 100 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 125 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 200 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 400, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 250 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingIncrement: 500 }), + 0, 0, 0, 0, 10, 35, 23, 865, 198, 500, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js new file mode 100644 index 0000000000..413aa6a02c --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-non-integer.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Rounding for roundingIncrement option +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +const result = earlier.until(later, { roundingIncrement: 2.5, roundingMode: "trunc" }); +TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 truncates to 2"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js new file mode 100644 index 0000000000..1c901e5176 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-out-of-range.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingIncrement option out of range +info: | + ToTemporalRoundingIncrement ( _normalizedOptions_ ) + + 1. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, *"number"*, *undefined*, *1*<sub>𝔽</sub>). + 2. If _increment_ is not finite, throw a *RangeError* exception. + 3. Let _integerIncrement_ be truncate(ℝ(_increment_)). + 4. If _integerIncrement_ < 1 or _integerIncrement_ > 10<sup>9</sup>, throw a *RangeError* exception. + 5. Return _integerIncrement_. +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(12, 34, 56, 0, 0, 5); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -Infinity })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: -1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 0.9 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: 1e9 + 1 })); +assert.throws(RangeError, () => earlier.until(later, { roundingIncrement: Infinity })); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js new file mode 100644 index 0000000000..2a26e524cb --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-seconds.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Valid values for roundingIncrement option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(3, 12, 34, 123, 456, 789); +const later = new Temporal.PlainTime(13, 47, 57, 988, 655, 322); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 1 }), + 0, 0, 0, 0, 10, 35, 23, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 2 }), + 0, 0, 0, 0, 10, 35, 22, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 3 }), + 0, 0, 0, 0, 10, 35, 21, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 4 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 5 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 6 }), + 0, 0, 0, 0, 10, 35, 18, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 10 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 12 }), + 0, 0, 0, 0, 10, 35, 12, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 15 }), + 0, 0, 0, 0, 10, 35, 15, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 20 }), + 0, 0, 0, 0, 10, 35, 20, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingIncrement: 30 }), + 0, 0, 0, 0, 10, 35, 0, 0, 0, 0, "seconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js new file mode 100644 index 0000000000..46a39fa264 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-undefined.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for roundingIncrement option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +const explicit = earlier.until(later, { roundingIncrement: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, "default roundingIncrement is 1"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js new file mode 100644 index 0000000000..d247679031 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingincrement-wrong-type.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for roundingIncrement option +info: | + sec-getoption step 8.a: + a. Set _value_ to ? ToNumber(value). + sec-temporal-totemporalroundingincrement step 5: + 5. Let _increment_ be ? GetOption(_normalizedOptions_, *"roundingIncrement"*, « Number », *undefined*, 1). + sec-temporal.plaintime.prototype.until step 10: + 10. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*). +includes: [temporalHelpers.js, compareArray.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); + +TemporalHelpers.checkRoundingIncrementOptionWrongType( + (roundingIncrement) => earlier.until(later, { roundingIncrement }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, descr), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js new file mode 100644 index 0000000000..df3a7ee979 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-ceil.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "ceil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 5], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 18], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -4]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 865], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "ceil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-expand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-expand.js new file mode 100644 index 0000000000..705de9a868 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-expand.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "expand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 5], [0, 0, 0, 0, -5]], + ["minutes", [0, 0, 0, 0, 4, 18], [0, 0, 0, 0, -4, -18]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 865], [0, 0, 0, 0, -4, -17, -4, -865]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "expand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js new file mode 100644 index 0000000000..11270082d7 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-floor.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "floor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -5]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -18]], + ["seconds", [0, 0, 0, 0, 4, 17, 4], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -865]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "floor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfCeil.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfCeil.js new file mode 100644 index 0000000000..d987d5c4a4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfCeil.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfCeil". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfCeil"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfEven.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfEven.js new file mode 100644 index 0000000000..239e861107 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfEven.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfEven". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfEven"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js new file mode 100644 index 0000000000..a8e5f26aef --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfExpand.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfExpand". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 198], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfExpand"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfFloor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfFloor.js new file mode 100644 index 0000000000..0908a4bd68 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfFloor.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfFloor". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -198]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfFloor"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfTrunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfTrunc.js new file mode 100644 index 0000000000..e5bae72f9d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-halfTrunc.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "halfTrunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 5], [0, 0, 0, 0, -4, -17, -5]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "halfTrunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js new file mode 100644 index 0000000000..76598d4a3d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-invalid-string.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: RangeError thrown when roundingMode option not one of the allowed string values +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +for (const roundingMode of ["other string", "cile", "CEIL", "ce\u0131l", "auto", "halfexpand", "floor\0"]) { + assert.throws(RangeError, () => earlier.until(later, { smallestUnit: "microsecond", roundingMode })); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js new file mode 100644 index 0000000000..a1f609d8d1 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-trunc.js @@ -0,0 +1,41 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Tests calculations with roundingMode "trunc". +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(8, 22, 36, 123, 456, 789); +const later = new Temporal.PlainTime(12, 39, 40, 987, 654, 289); + +const expected = [ + ["hours", [0, 0, 0, 0, 4], [0, 0, 0, 0, -4]], + ["minutes", [0, 0, 0, 0, 4, 17], [0, 0, 0, 0, -4, -17]], + ["seconds", [0, 0, 0, 0, 4, 17, 4], [0, 0, 0, 0, -4, -17, -4]], + ["milliseconds", [0, 0, 0, 0, 4, 17, 4, 864], [0, 0, 0, 0, -4, -17, -4, -864]], + ["microseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197], [0, 0, 0, 0, -4, -17, -4, -864, -197]], + ["nanoseconds", [0, 0, 0, 0, 4, 17, 4, 864, 197, 500], [0, 0, 0, 0, -4, -17, -4, -864, -197, -500]], +]; + +const roundingMode = "trunc"; + +expected.forEach(([smallestUnit, expectedPositive, expectedNegative]) => { + const [py, pm = 0, pw = 0, pd = 0, ph = 0, pmin = 0, ps = 0, pms = 0, pµs = 0, pns = 0] = expectedPositive; + const [ny, nm = 0, nw = 0, nd = 0, nh = 0, nmin = 0, ns = 0, nms = 0, nµs = 0, nns = 0] = expectedNegative; + TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit, roundingMode }), + py, pm, pw, pd, ph, pmin, ps, pms, pµs, pns, + `rounds to ${smallestUnit} (roundingMode = ${roundingMode}, positive case)` + ); + TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit, roundingMode }), + ny, nm, nw, nd, nh, nmin, ns, nms, nµs, nns, + `rounds to ${smallestUnit} (rounding mode = ${roundingMode}, negative case)` + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js new file mode 100644 index 0000000000..c6cef9687a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-undefined.js @@ -0,0 +1,93 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Fallback value for roundingMode option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = Temporal.PlainTime.from("08:22:36.123456789"); +const later = Temporal.PlainTime.from("12:39:40.987654321"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "hours" }), + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours", roundingMode: undefined }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "hours" }), + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, "hours"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "minutes" }), + 0, 0, 0, 0, 4, 17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "minutes" }), + 0, 0, 0, 0, -4, -17, 0, 0, 0, 0, "minutes"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "seconds" }), + 0, 0, 0, 0, 4, 17, 4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "seconds" }), + 0, 0, 0, 0, -4, -17, -4, 0, 0, 0, "seconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "milliseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, 0, 0, "milliseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "microseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, 0, "microseconds"); + +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + earlier.until(later, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, 4, 17, 4, 864, 197, 532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds", roundingMode: undefined }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); +TemporalHelpers.assertDuration( + later.until(earlier, { smallestUnit: "nanoseconds" }), + 0, 0, 0, 0, -4, -17, -4, -864, -197, -532, "nanoseconds"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js new file mode 100644 index 0000000000..80fe5287ae --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/roundingmode-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for roundingMode option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 123, 987, 500); +TemporalHelpers.checkStringOptionWrongType("roundingMode", "trunc", + (roundingMode) => earlier.until(later, { smallestUnit: "microsecond", roundingMode }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 123, 987, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js new file mode 100644 index 0000000000..64101bd085 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-invalid-string.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: RangeError thrown when smallestUnit option not one of the allowed string values +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 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`); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js new file mode 100644 index 0000000000..7fa86c19b3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-plurals-accepted.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Plural units are accepted as well for the smallestUnit option +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const later = new Temporal.PlainTime(13, 35, 57, 988, 655, 322); +const validUnits = [ + "hour", + "minute", + "second", + "millisecond", + "microsecond", + "nanosecond", +]; +TemporalHelpers.checkPluralUnitsAccepted((smallestUnit) => earlier.until(later, { smallestUnit }), validUnits); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js new file mode 100644 index 0000000000..e32c3a81ea --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-undefined.js @@ -0,0 +1,22 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Fallback value for smallestUnit option +includes: [temporalHelpers.js] +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 explicit = earlier.until(later, { smallestUnit: undefined }); +TemporalHelpers.assertDuration(explicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const implicit = earlier.until(later, {}); +TemporalHelpers.assertDuration(implicit, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); +const lambda = earlier.until(later, () => {}); +TemporalHelpers.assertDuration(lambda, 0, 0, 0, 0, 1, 1, 1, 987, 654, 321, "default smallestUnit is nanosecond"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js new file mode 100644 index 0000000000..a840df2f93 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/smallestunit-wrong-type.js @@ -0,0 +1,19 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.until +description: Type conversions for smallestUnit option +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const earlier = new Temporal.PlainTime(12, 34, 56, 0, 0, 0); +const later = new Temporal.PlainTime(13, 35, 57, 987, 654, 321); +TemporalHelpers.checkStringOptionWrongType("smallestUnit", "microsecond", + (smallestUnit) => earlier.until(later, { smallestUnit }), + (result, descr) => TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 1, 1, 1, 987, 654, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js new file mode 100644 index 0000000000..2cd3a81649 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/until/year-zero.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: Negative zero, as an extended year, is rejected +features: [Temporal, arrow-function] +---*/ + +const invalidStrings = [ + "-000000-12-07T03:24:30", + "-000000-12-07T03:24:30+01:00", + "-000000-12-07T03:24:30+00:00[UTC]", +]; +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +invalidStrings.forEach((arg) => { + assert.throws( + RangeError, + () => instance.until(arg), + "reject minus zero as extended year" + ); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js new file mode 100644 index 0000000000..1b9dc24a7d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/basic.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Basic tests for valueOf(). +features: [Temporal] +---*/ + +const plainTime = Temporal.PlainTime.from("09:36:29.123456789"); +const plainTime2 = Temporal.PlainTime.from("09:36:29.123456789"); + +assert.throws(TypeError, () => plainTime.valueOf(), "valueOf"); +assert.throws(TypeError, () => plainTime < plainTime, "<"); +assert.throws(TypeError, () => plainTime <= plainTime, "<="); +assert.throws(TypeError, () => plainTime > plainTime, ">"); +assert.throws(TypeError, () => plainTime >= plainTime, ">="); +assert.sameValue(plainTime === plainTime, true, "==="); +assert.sameValue(plainTime === plainTime2, false, "==="); +assert.sameValue(plainTime !== plainTime, false, "!=="); +assert.sameValue(plainTime !== plainTime2, true, "!=="); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/branding.js new file mode 100644 index 0000000000..c877532a8a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/branding.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const valueOf = Temporal.PlainTime.prototype.valueOf; + +assert.sameValue(typeof valueOf, "function"); + +assert.throws(TypeError, () => valueOf.call(undefined), "undefined"); +assert.throws(TypeError, () => valueOf.call(null), "null"); +assert.throws(TypeError, () => valueOf.call(true), "true"); +assert.throws(TypeError, () => valueOf.call(""), "empty string"); +assert.throws(TypeError, () => valueOf.call(Symbol()), "symbol"); +assert.throws(TypeError, () => valueOf.call(1), "1"); +assert.throws(TypeError, () => valueOf.call({}), "plain object"); +assert.throws(TypeError, () => valueOf.call(Temporal.PlainTime), "Temporal.PlainTime"); +assert.throws(TypeError, () => valueOf.call(Temporal.PlainTime.prototype), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js new file mode 100644 index 0000000000..b9cf15bcd4 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: > + Tests that Temporal.PlainTime.prototype.valueOf + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.valueOf), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.valueOf), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.valueOf), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.valueOf.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js new file mode 100644 index 0000000000..d3d22c93cd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Temporal.PlainTime.prototype.valueOf.length is 0 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.valueOf, "length", { + value: 0, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js new file mode 100644 index 0000000000..33264a7a6f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: Temporal.PlainTime.prototype.valueOf.name is "valueOf". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.valueOf, "name", { + value: "valueOf", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js new file mode 100644 index 0000000000..46477ced1d --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: > + Temporal.PlainTime.prototype.valueOf does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.valueOf(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.valueOf), false, + "isConstructor(Temporal.PlainTime.prototype.valueOf)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js new file mode 100644 index 0000000000..f1473ac5a0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.valueof +description: The "valueOf" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.valueOf, + "function", + "`typeof PlainTime.prototype.valueOf` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "valueOf", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/valueOf/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js new file mode 100644 index 0000000000..c9eddc8b08 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/argument-not-object.js @@ -0,0 +1,37 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: TypeError is thrown if a primitive is passed, including ISO strings +info: | + Temporal.PlainTime.prototype.with ( temporalTimeLike [ , options ] ) + + 3. If Type(temporalTimeLike) is not Object, then + a. Throw a TypeError exception. +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +assert.throws(TypeError, () => instance.with(undefined), "undefined"); +assert.throws(TypeError, () => instance.with(null), "null"); +assert.throws(TypeError, () => instance.with(true), "true"); +assert.throws(TypeError, () => instance.with(Symbol()), "symbol"); +assert.throws(TypeError, () => instance.with(1), "1"); +assert.throws(TypeError, () => instance.with(1n), "1n"); + +const strings = [ + "", + "18:05:42.577", + "2019-05-17T18:05:42.577", + "2019-05-17T18:05:42.577Z", + "2019-05-17", + "42", +]; +for (const s of strings) { + assert.throws(TypeError, () => instance.with(s), s); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js new file mode 100644 index 0000000000..2fa17fda70 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/basic.js @@ -0,0 +1,39 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Basic tests for with(). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(15, 23, 30, 123, 456, 789); +TemporalHelpers.assertPlainTime(plainTime, 15, 23, 30, 123, 456, 789, "initial"); + +const hour = plainTime.with({ hour: 3 }); +TemporalHelpers.assertPlainTime(hour, 3, 23, 30, 123, 456, 789, "hour"); + +const minute = plainTime.with({ minute: 3 }); +TemporalHelpers.assertPlainTime(minute, 15, 3, 30, 123, 456, 789, "minute"); + +const second = plainTime.with({ second: 3 }); +TemporalHelpers.assertPlainTime(second, 15, 23, 3, 123, 456, 789, "second"); + +const millisecond = plainTime.with({ millisecond: 3 }); +TemporalHelpers.assertPlainTime(millisecond, 15, 23, 30, 3, 456, 789, "millisecond"); + +const microsecond = plainTime.with({ microsecond: 3 }); +TemporalHelpers.assertPlainTime(microsecond, 15, 23, 30, 123, 3, 789, "microsecond"); + +const nanosecond = plainTime.with({ nanosecond: 3 }); +TemporalHelpers.assertPlainTime(nanosecond, 15, 23, 30, 123, 456, 3, "nanosecond"); + +const combined = plainTime.with({ minute: 8, nanosecond: 3 }); +TemporalHelpers.assertPlainTime(combined, 15, 8, 30, 123, 456, 3, "combined"); + +const plural = plainTime.with({ minutes: 8, nanosecond: 3 }); +TemporalHelpers.assertPlainTime(plural, 15, 23, 30, 123, 456, 3, "plural"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/branding.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/branding.js new file mode 100644 index 0000000000..f2d4368c5e --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/branding.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Throw a TypeError if the receiver is invalid +features: [Symbol, Temporal] +---*/ + +const with_ = Temporal.PlainTime.prototype.with; + +assert.sameValue(typeof with_, "function"); + +const args = [{ hour: 7 }]; + +assert.throws(TypeError, () => with_.apply(undefined, args), "undefined"); +assert.throws(TypeError, () => with_.apply(null, args), "null"); +assert.throws(TypeError, () => with_.apply(true, args), "true"); +assert.throws(TypeError, () => with_.apply("", args), "empty string"); +assert.throws(TypeError, () => with_.apply(Symbol(), args), "symbol"); +assert.throws(TypeError, () => with_.apply(1, args), "1"); +assert.throws(TypeError, () => with_.apply({}, args), "plain object"); +assert.throws(TypeError, () => with_.apply(Temporal.PlainTime, args), "Temporal.PlainTime"); +assert.throws(TypeError, () => with_.apply(Temporal.PlainTime.prototype, args), "Temporal.PlainTime.prototype"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/browser.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/browser.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js new file mode 100644 index 0000000000..53ffd00651 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/builtin.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: > + Tests that Temporal.PlainTime.prototype.with + meets the requirements for built-in objects defined by the + introduction of chapter 17 of the ECMAScript Language Specification. +info: | + Built-in functions that are not constructors do not have a "prototype" property unless + otherwise specified in the description of a particular function. + + Unless specified otherwise, a built-in object that is callable as a function is a built-in + function object with the characteristics described in 10.3. Unless specified otherwise, the + [[Extensible]] internal slot of a built-in object initially has the value true. + + Unless otherwise specified every built-in function and every built-in constructor has the + Function prototype object [...] as the value of its [[Prototype]] internal slot. +features: [Temporal] +---*/ + +assert.sameValue(Object.isExtensible(Temporal.PlainTime.prototype.with), + true, "Built-in objects must be extensible."); + +assert.sameValue(Object.prototype.toString.call(Temporal.PlainTime.prototype.with), + "[object Function]", "Object.prototype.toString"); + +assert.sameValue(Object.getPrototypeOf(Temporal.PlainTime.prototype.with), + Function.prototype, "prototype"); + +assert.sameValue(Temporal.PlainTime.prototype.with.hasOwnProperty("prototype"), + false, "prototype property"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js new file mode 100644 index 0000000000..4ea654c715 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/copy-properties-not-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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: PreparePartialTemporalFields copies only defined properties of source object +info: | + 4. For each value _property_ of _fieldNames_, do + a. Let _value_ be ? Get(_fields_, _property_). + b. If _value_ is not *undefined*, then + ... + iii. Perform ! CreateDataPropertyOrThrow(_result_, _property_, _value_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(9, 45, 55); + +TemporalHelpers.assertPlainTime(plainTime.with({ hour: 8, second: undefined }), + 8, 45, 55, 0, 0, 0, + "only the properties that are present and defined in the plain object are copied" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js new file mode 100644 index 0000000000..6827322b34 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/infinity-throws-rangeerror.js @@ -0,0 +1,27 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: Throws if any value in the property bag is Infinity or -Infinity +esid: sec-temporal.plaintime.prototype.with +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +[Infinity, -Infinity].forEach((inf) => { + ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => { + ["constrain", "reject"].forEach((overflow) => { + assert.throws(RangeError, () => instance.with({ [prop]: inf }, { overflow }), `${prop} property cannot be ${inf} (overflow ${overflow}`); + + const calls = []; + const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop); + assert.throws(RangeError, () => instance.with({ [prop]: obj }, { overflow })); + assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value"); + }); + }); +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js new file mode 100644 index 0000000000..b51dcb2cf9 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/length.js @@ -0,0 +1,28 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Temporal.PlainTime.prototype.with.length is 1 +info: | + Every built-in function object, including constructors, has a "length" property whose value is + an integer. Unless otherwise specified, this value is equal to the largest number of named + arguments shown in the subclause headings for the function description. Optional parameters + (which are indicated with brackets: [ ]) or rest parameters (which are shown using the form + «...name») are not included in the default argument count. + + Unless otherwise specified, the "length" property of a built-in function object has the + attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.with, "length", { + value: 1, + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js new file mode 100644 index 0000000000..e37f7e45de --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/name.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Temporal.PlainTime.prototype.with.name is "with". +info: | + Every built-in function object, including constructors, that is not identified as an anonymous + function has a "name" property whose value is a String. Unless otherwise specified, this value + is the name that is given to the function in this specification. + + Unless otherwise specified, the "name" property of a built-in function object, if it exists, + has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +verifyProperty(Temporal.PlainTime.prototype.with, "name", { + value: "with", + writable: false, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js new file mode 100644 index 0000000000..4446eb754b --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/not-a-constructor.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: > + Temporal.PlainTime.prototype.with does not implement [[Construct]], is not new-able +info: | + Built-in function objects that are not identified as constructors do not implement the + [[Construct]] internal method unless otherwise specified in the description of a particular + function. +includes: [isConstructor.js] +features: [Reflect.construct, Temporal] +---*/ + +assert.throws(TypeError, () => { + new Temporal.PlainTime.prototype.with(); +}, "Calling as constructor"); + +assert.sameValue(isConstructor(Temporal.PlainTime.prototype.with), false, + "isConstructor(Temporal.PlainTime.prototype.with)"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js new file mode 100644 index 0000000000..7cd1abbf1a --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-invalid.js @@ -0,0 +1,16 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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 a primitive is passed as the options argument +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12); +for (const badOptions of [null, true, "hello", Symbol("foo"), 1, 1n]) { + assert.throws(TypeError, () => plainTime.with({ hour: 3 }, badOptions)); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-object.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-object.js new file mode 100644 index 0000000000..25a0d37bfa --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-object.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Empty or a function object may be used as options +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(); + +const result1 = instance.with({ minute: 45 }, {}); +TemporalHelpers.assertPlainTime( + result1, 0, 45, 0, 0, 0, 0, + "options may be an empty plain object" +); + +const result2 = instance.with({ minute: 45 }, () => {}); +TemporalHelpers.assertPlainTime( + result2, 0, 45, 0, 0, 0, 0, + "options may be a function object" +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js new file mode 100644 index 0000000000..02c8659e12 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-undefined.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +includes: [temporalHelpers.js] +description: Verify that undefined options are handled correctly. +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const fields = { minute: 60 }; + +const explicit = time.with(fields, undefined); +TemporalHelpers.assertPlainTime(explicit, 12, 59, 56, 987, 654, 321, "explicit"); + +const implicit = time.with(fields); +TemporalHelpers.assertPlainTime(implicit, 12, 59, 56, 987, 654, 321, "implicit"); + +const lambda = time.with(fields, () => {}); +TemporalHelpers.assertPlainTime(lambda, 12, 59, 56, 987, 654, 321, "lambda"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js new file mode 100644 index 0000000000..f15373d377 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/options-wrong-type.js @@ -0,0 +1,26 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2022 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.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}`); +}; + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js new file mode 100644 index 0000000000..fdc9c6cb57 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/order-of-operations.js @@ -0,0 +1,59 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2020 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Properties on an object passed to with() are accessed in the correct order +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const instance = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); +const expected = [ + // RejectObjectWithCalendarOrTimeZone + "get fields.calendar", + "get fields.timeZone", + // ToTemporalOverflow + "get options.overflow", + "get options.overflow.toString", + "call options.overflow.toString", + // ToTemporalTimeRecord + "get fields.hour", + "get fields.hour.valueOf", + "call fields.hour.valueOf", + "get fields.microsecond", + "get fields.microsecond.valueOf", + "call fields.microsecond.valueOf", + "get fields.millisecond", + "get fields.millisecond.valueOf", + "call fields.millisecond.valueOf", + "get fields.minute", + "get fields.minute.valueOf", + "call fields.minute.valueOf", + "get fields.nanosecond", + "get fields.nanosecond.valueOf", + "call fields.nanosecond.valueOf", + "get fields.second", + "get fields.second.valueOf", + "call fields.second.valueOf", +]; +const actual = []; + +const fields = TemporalHelpers.propertyBagObserver(actual, { + hour: 1.7, + minute: 1.7, + second: 1.7, + millisecond: 1.7, + microsecond: 1.7, + nanosecond: 1.7, +}, "fields"); + +const options = TemporalHelpers.propertyBagObserver(actual, { + overflow: "constrain", +}, "options"); + +const result = instance.with(fields, options); +assert.compareArray(actual, expected, "order of operations"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js new file mode 100644 index 0000000000..f5e60db95f --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-invalid-string.js @@ -0,0 +1,29 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: RangeError thrown when overflow option not one of the allowed string values +info: | + sec-getoption step 10: + 10. If _values_ is not *undefined* and _values_ does not contain an element equal to _value_, throw a *RangeError* exception. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); + +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}")` + ); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js new file mode 100644 index 0000000000..1d44db4ab3 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-undefined.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Fallback value for overflow option +info: | + sec-getoption step 3: + 3. If _value_ is *undefined*, return _fallback_. + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); +const explicit = time.with({ minute: 67 }, { overflow: undefined }); +TemporalHelpers.assertPlainTime(explicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); +const implicit = time.with({ minute: 67 }, {}); +TemporalHelpers.assertPlainTime(implicit, 12, 59, 0, 0, 0, 0, "default overflow is constrain"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js new file mode 100644 index 0000000000..96e3ca15dd --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/overflow-wrong-type.js @@ -0,0 +1,25 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Type conversions for overflow option +info: | + sec-getoption step 9.a: + a. Set _value_ to ? ToString(_value_). + sec-temporal-totemporaloverflow step 1: + 1. Return ? GetOption(_normalizedOptions_, *"overflow"*, « String », « *"constrain"*, *"reject"* », *"constrain"*). + sec-temporal.plaintime.prototype.with step 11: + 11. Let _overflow_ be ? ToTemporalOverflow(_options_). +includes: [compareArray.js, temporalHelpers.js] +features: [Temporal] +---*/ + +const time = new Temporal.PlainTime(12); +TemporalHelpers.checkStringOptionWrongType("overflow", "constrain", + (overflow) => time.with({ minute: 45 }, { overflow }), + (result, descr) => TemporalHelpers.assertPlainTime(result, 12, 45, 0, 0, 0, 0, descr), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js new file mode 100644 index 0000000000..4b9f9c0316 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/plaintimelike-invalid.js @@ -0,0 +1,50 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 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: Throws TypeError on an argument that is not a PlainTime-like property bag +features: [Temporal] +---*/ + +const plainTime = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + +const tests = [ + // Step 3. + [undefined], + [null], + [true], + ["2019-05-17"], + ["2019-05-17T12:34"], + ["2019-05-17T12:34Z"], + ["18:05:42.577"], + ["42"], + [Symbol(), "symbol"], + [42, "number"], + [42n, "bigint"], + + // Step 4. + [Temporal.PlainDate.from("2019-05-17"), "PlainDate"], + [Temporal.PlainDateTime.from("2019-05-17T12:34"), "PlainDateTime"], + [Temporal.PlainMonthDay.from("2019-05-17"), "PlainMonthDay"], + [Temporal.PlainTime.from("12:34"), "PlainTime"], + [Temporal.PlainYearMonth.from("2019-05-17"), "PlainYearMonth"], + [Temporal.ZonedDateTime.from("2019-05-17T12:34Z[UTC]"), "ZonedDateTime"], + + // Step 5-6. + [{ hour: 14, calendar: "iso8601" }, "calendar"], + + // Step 7-8. + [{ hour: 14, timeZone: "UTC" }, "timeZone"], + + // Step 9. + [{}, "empty object"], + [{ hours: 14 }, "only plural property"], +]; + +for (const [value, message = String(value)] of tests) { + assert.throws(TypeError, () => plainTime.with(value), message); +} + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js new file mode 100644 index 0000000000..e4a1c0ca44 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/prop-desc.js @@ -0,0 +1,24 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: The "with" property of Temporal.PlainTime.prototype +includes: [propertyHelper.js] +features: [Temporal] +---*/ + +assert.sameValue( + typeof Temporal.PlainTime.prototype.with, + "function", + "`typeof PlainTime.prototype.with` is `function`" +); + +verifyProperty(Temporal.PlainTime.prototype, "with", { + writable: true, + enumerable: false, + configurable: true, +}); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js new file mode 100644 index 0000000000..eda1477282 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/shell.js @@ -0,0 +1,24 @@ +// GENERATED, DO NOT EDIT +// file: isConstructor.js +// Copyright (C) 2017 André Bargull. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: | + Test if a given function is a constructor function. +defines: [isConstructor] +features: [Reflect.construct] +---*/ + +function isConstructor(f) { + if (typeof f !== "function") { + throw new Test262Error("isConstructor invoked with a non-function value"); + } + + try { + Reflect.construct(function(){}, [], f); + } catch (e) { + return false; + } + return true; +} diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js new file mode 100644 index 0000000000..a9112670f6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/prototype/with/subclassing-ignored.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.with +description: Objects of a subclass are never created as return values for with() +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +TemporalHelpers.checkSubclassingIgnored( + Temporal.PlainTime, + [12, 34, 56, 987, 654, 321], + "with", + [{ nanosecond: 1 }], + (result) => TemporalHelpers.assertPlainTime(result, 12, 34, 56, 987, 654, 1), +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js new file mode 100644 index 0000000000..5eceb3c5ee --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/second-undefined.js @@ -0,0 +1,20 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime +description: Second argument defaults to 0 if not given +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +const args = [12, 34]; + +const explicit = new Temporal.PlainTime(...args, undefined); +TemporalHelpers.assertPlainTime(explicit, ...args, 0, 0, 0, 0, "explicit"); + +const implicit = new Temporal.PlainTime(...args); +TemporalHelpers.assertPlainTime(implicit, ...args, 0, 0, 0, 0, "implicit"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/shell.js diff --git a/js/src/tests/test262/built-ins/Temporal/PlainTime/subclass.js b/js/src/tests/test262/built-ins/Temporal/PlainTime/subclass.js new file mode 100644 index 0000000000..4fae03ce38 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/PlainTime/subclass.js @@ -0,0 +1,21 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (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 +description: Test for Temporal.PlainTime subclassing. +includes: [temporalHelpers.js] +features: [Temporal] +---*/ + +class CustomPlainTime extends Temporal.PlainTime { +} + +const instance = new CustomPlainTime(12, 34, 56, 987, 654, 321); +TemporalHelpers.assertPlainTime(instance, 12, 34, 56, 987, 654, 321); +assert.sameValue(Object.getPrototypeOf(instance), CustomPlainTime.prototype, "Instance of CustomPlainTime"); +assert(instance instanceof CustomPlainTime, "Instance of CustomPlainTime"); +assert(instance instanceof Temporal.PlainTime, "Instance of Temporal.PlainTime"); + +reportCompare(0, 0); |