AbstractOperations.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #pragma once
  9. #include <AK/Variant.h>
  10. #include <LibGC/Ptr.h>
  11. #include <LibJS/Forward.h>
  12. #include <LibJS/Runtime/Completion.h>
  13. #include <LibJS/Runtime/VM.h>
  14. #include <LibJS/Runtime/ValueInlines.h>
  15. #include <math.h>
  16. namespace JS::Temporal {
  17. // https://tc39.es/proposal-temporal/#sec-temporal-units
  18. enum class Unit {
  19. Year,
  20. Month,
  21. Week,
  22. Day,
  23. Hour,
  24. Minute,
  25. Second,
  26. Millisecond,
  27. Microsecond,
  28. Nanosecond,
  29. };
  30. StringView temporal_unit_to_string(Unit);
  31. // https://tc39.es/proposal-temporal/#sec-temporal-units
  32. enum class UnitCategory {
  33. Date,
  34. Time,
  35. };
  36. // https://tc39.es/proposal-temporal/#sec-temporal-units
  37. enum class UnitGroup {
  38. Date,
  39. Time,
  40. DateTime,
  41. };
  42. struct Unset { };
  43. using RoundingIncrement = Variant<Unset, u64>;
  44. struct RelativeTo {
  45. // FIXME: Make these objects represent their actual types when we re-implement them.
  46. GC::Ptr<JS::Object> plain_relative_to; // [[PlainRelativeTo]]
  47. GC::Ptr<JS::Object> zoned_relative_to; // [[ZonedRelativeTo]]
  48. };
  49. ThrowCompletionOr<RelativeTo> get_temporal_relative_to_option(VM&, Object const& options);
  50. bool is_calendar_unit(Unit);
  51. UnitCategory temporal_unit_category(Unit);
  52. ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM&, StringView iso_string);
  53. // 13.38 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
  54. template<typename... Args>
  55. ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, Value argument, ErrorType error_type, Args&&... args)
  56. {
  57. // 1. Let number be ? ToNumber(argument).
  58. auto number = TRY(argument.to_number(vm));
  59. // 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
  60. if (number.is_nan() || number.is_infinity())
  61. return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
  62. // 3. Return truncate(ℝ(number)).
  63. return trunc(number.as_double());
  64. }
  65. // 13.38 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
  66. // AD-HOC: We often need to use this AO when we have a parsed StringView. This overload allows callers to avoid creating
  67. // a PrimitiveString for the primary definition.
  68. template<typename... Args>
  69. ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, StringView argument, ErrorType error_type, Args&&... args)
  70. {
  71. // 1. Let number be ? ToNumber(argument).
  72. auto number = string_to_number(argument);
  73. // 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
  74. if (isnan(number) || isinf(number))
  75. return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
  76. // 3. Return truncate(ℝ(number)).
  77. return trunc(number);
  78. }
  79. // 13.39 ToIntegerIfIntegral ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerifintegral
  80. template<typename... Args>
  81. ThrowCompletionOr<double> to_integer_if_integral(VM& vm, Value argument, ErrorType error_type, Args&&... args)
  82. {
  83. // 1. Let number be ? ToNumber(argument).
  84. auto number = TRY(argument.to_number(vm));
  85. // 2. If number is not an integral Number, throw a RangeError exception.
  86. if (!number.is_integral_number())
  87. return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
  88. // 3. Return ℝ(number).
  89. return number.as_double();
  90. }
  91. enum class OptionType {
  92. Boolean,
  93. String,
  94. };
  95. struct DefaultRequired { };
  96. using OptionDefault = Variant<DefaultRequired, Empty, bool, StringView, double>;
  97. ThrowCompletionOr<GC::Ref<Object>> get_options_object(VM&, Value options);
  98. ThrowCompletionOr<Value> get_option(VM&, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan<StringView> values, OptionDefault const&);
  99. template<size_t Size>
  100. ThrowCompletionOr<Value> get_option(VM& vm, Object const& options, PropertyKey const& property, OptionType type, StringView const (&values)[Size], OptionDefault const& default_)
  101. {
  102. return get_option(vm, options, property, type, ReadonlySpan<StringView> { values }, default_);
  103. }
  104. }