BigIntPrototype.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Function.h>
  7. #include <AK/TypeCasts.h>
  8. #include <LibJS/Runtime/AbstractOperations.h>
  9. #include <LibJS/Runtime/BigIntObject.h>
  10. #include <LibJS/Runtime/BigIntPrototype.h>
  11. #include <LibJS/Runtime/Completion.h>
  12. #include <LibJS/Runtime/Error.h>
  13. #include <LibJS/Runtime/GlobalObject.h>
  14. #include <LibJS/Runtime/Intl/NumberFormat.h>
  15. #include <LibJS/Runtime/Intl/NumberFormatConstructor.h>
  16. namespace JS {
  17. GC_DEFINE_ALLOCATOR(BigIntPrototype);
  18. BigIntPrototype::BigIntPrototype(Realm& realm)
  19. : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype())
  20. {
  21. }
  22. void BigIntPrototype::initialize(Realm& realm)
  23. {
  24. auto& vm = this->vm();
  25. Base::initialize(realm);
  26. u8 attr = Attribute::Writable | Attribute::Configurable;
  27. define_native_function(realm, vm.names.toString, to_string, 0, attr);
  28. define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr);
  29. define_native_function(realm, vm.names.valueOf, value_of, 0, attr);
  30. // 21.2.3.5 BigInt.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-bigint.prototype-@@tostringtag
  31. define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, vm.names.BigInt.as_string()), Attribute::Configurable);
  32. }
  33. // thisBigIntValue ( value ), https://tc39.es/ecma262/#thisbigintvalue
  34. static ThrowCompletionOr<GC::Ref<BigInt>> this_bigint_value(VM& vm, Value value)
  35. {
  36. // 1. If value is a BigInt, return value.
  37. if (value.is_bigint())
  38. return value.as_bigint();
  39. // 2. If value is an Object and value has a [[BigIntData]] internal slot, then
  40. if (value.is_object() && is<BigIntObject>(value.as_object())) {
  41. // a. Assert: value.[[BigIntData]] is a BigInt.
  42. // b. Return value.[[BigIntData]].
  43. return static_cast<BigIntObject&>(value.as_object()).bigint();
  44. }
  45. // 3. Throw a TypeError exception.
  46. return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "BigInt");
  47. }
  48. // 21.2.3.3 BigInt.prototype.toString ( [ radix ] ), https://tc39.es/ecma262/#sec-bigint.prototype.tostring
  49. JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_string)
  50. {
  51. // 1. Let x be ? thisBigIntValue(this value).
  52. auto bigint = TRY(this_bigint_value(vm, vm.this_value()));
  53. // 2. If radix is undefined, let radixMV be 10.
  54. double radix = 10;
  55. // 3. Else, let radixMV be ? ToIntegerOrInfinity(radix).
  56. if (!vm.argument(0).is_undefined()) {
  57. radix = TRY(vm.argument(0).to_integer_or_infinity(vm));
  58. // 4. If radixMV is not in the inclusive interval from 2 to 36, throw a RangeError exception.
  59. if (radix < 2 || radix > 36)
  60. return vm.throw_completion<RangeError>(ErrorType::InvalidRadix);
  61. }
  62. // 5. Return BigInt::toString(x, radixMV).
  63. return PrimitiveString::create(vm, bigint->big_integer().to_base_deprecated(radix));
  64. }
  65. // 21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-bigint.prototype.tolocalestring
  66. // 19.3.1 BigInt.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-bigint.prototype.tolocalestring
  67. JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_locale_string)
  68. {
  69. auto& realm = *vm.current_realm();
  70. auto locales = vm.argument(0);
  71. auto options = vm.argument(1);
  72. // 1. Let x be ? thisBigIntValue(this value).
  73. auto bigint = TRY(this_bigint_value(vm, vm.this_value()));
  74. // 2. Let numberFormat be ? Construct(%NumberFormat%, « locales, options »).
  75. auto* number_format = static_cast<Intl::NumberFormat*>(TRY(construct(vm, realm.intrinsics().intl_number_format_constructor(), locales, options)).ptr());
  76. // 3. Return ? FormatNumeric(numberFormat, x).
  77. auto formatted = Intl::format_numeric(*number_format, Value(bigint));
  78. return PrimitiveString::create(vm, move(formatted));
  79. }
  80. // 21.2.3.4 BigInt.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-bigint.prototype.valueof
  81. JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::value_of)
  82. {
  83. // 1. Return ? thisBigIntValue(this value).
  84. return TRY(this_bigint_value(vm, vm.this_value()));
  85. }
  86. }