PlainTimeConstructor.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/GlobalObject.h>
  7. #include <LibJS/Runtime/Temporal/PlainTime.h>
  8. #include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
  9. namespace JS::Temporal {
  10. // 4.1 The Temporal.PlainTime Constructor, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-constructor
  11. PlainTimeConstructor::PlainTimeConstructor(GlobalObject& global_object)
  12. : NativeFunction(vm().names.PlainTime.as_string(), *global_object.function_prototype())
  13. {
  14. }
  15. void PlainTimeConstructor::initialize(GlobalObject& global_object)
  16. {
  17. NativeFunction::initialize(global_object);
  18. auto& vm = this->vm();
  19. // 4.2.1 Temporal.PlainTime.prototype, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-prototype
  20. define_direct_property(vm.names.prototype, global_object.temporal_plain_time_prototype(), 0);
  21. define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
  22. }
  23. // 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
  24. Value PlainTimeConstructor::call()
  25. {
  26. auto& vm = this->vm();
  27. // 1. If NewTarget is undefined, throw a TypeError exception.
  28. vm.throw_exception<TypeError>(global_object(), ErrorType::ConstructorWithoutNew, "Temporal.PlainTime");
  29. return {};
  30. }
  31. // 4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime
  32. Value PlainTimeConstructor::construct(FunctionObject& new_target)
  33. {
  34. auto& vm = this->vm();
  35. auto& global_object = this->global_object();
  36. // 2. Let hour be ? ToIntegerOrInfinity(hour).
  37. auto hour = vm.argument(0).to_integer_or_infinity(global_object);
  38. if (vm.exception())
  39. return {};
  40. // 3. If hour is +∞ or -∞, throw a RangeError exception.
  41. if (Value(hour).is_infinity()) {
  42. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  43. return {};
  44. }
  45. // 4. Let minute be ? ToIntegerOrInfinity(hour).
  46. auto minute = vm.argument(1).to_integer_or_infinity(global_object);
  47. if (vm.exception())
  48. return {};
  49. // 5. If minute is +∞ or -∞, throw a RangeError exception.
  50. if (Value(minute).is_infinity()) {
  51. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  52. return {};
  53. }
  54. // 6. Let second be ? ToIntegerOrInfinity(hour).
  55. auto second = vm.argument(2).to_integer_or_infinity(global_object);
  56. if (vm.exception())
  57. return {};
  58. // 7. If second is +∞ or -∞, throw a RangeError exception.
  59. if (Value(second).is_infinity()) {
  60. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  61. return {};
  62. }
  63. // 8. Let millisecond be ? ToIntegerOrInfinity(hour).
  64. auto millisecond = vm.argument(3).to_integer_or_infinity(global_object);
  65. if (vm.exception())
  66. return {};
  67. // 9. If millisecond is +∞ or -∞, throw a RangeError exception.
  68. if (Value(millisecond).is_infinity()) {
  69. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  70. return {};
  71. }
  72. // 10. Let microsecond be ? ToIntegerOrInfinity(hour).
  73. auto microsecond = vm.argument(4).to_integer_or_infinity(global_object);
  74. if (vm.exception())
  75. return {};
  76. // 11. If microsecond is +∞ or -∞, throw a RangeError exception.
  77. if (Value(microsecond).is_infinity()) {
  78. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  79. return {};
  80. }
  81. // 12. Let nanosecond be ? ToIntegerOrInfinity(hour).
  82. auto nanosecond = vm.argument(5).to_integer_or_infinity(global_object);
  83. if (vm.exception())
  84. return {};
  85. // 13. If nanosecond is +∞ or -∞, throw a RangeError exception.
  86. if (Value(nanosecond).is_infinity()) {
  87. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  88. return {};
  89. }
  90. // IMPLEMENTATION DEFINED: This is an optimization that allows us to treat these doubles as normal integers from this point onwards.
  91. // This does not change the exposed behaviour as the call to CreateTemporalTime will immediately check that these values are valid
  92. // ISO values (for hours: 0 - 23, for minutes and seconds: 0 - 59, milliseconds, microseconds, and nanoseconds: 0 - 999) all of which
  93. // are subsets of this check.
  94. if (!AK::is_within_range<u8>(hour) || !AK::is_within_range<u8>(minute) || !AK::is_within_range<u8>(second) || !AK::is_within_range<u16>(millisecond) || !AK::is_within_range<u16>(microsecond) || !AK::is_within_range<u16>(nanosecond)) {
  95. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  96. return {};
  97. }
  98. // 14. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget).
  99. return create_temporal_time(global_object, hour, minute, second, millisecond, microsecond, nanosecond, &new_target);
  100. }
  101. }