builtin_number.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package otto
  2. import (
  3. "math"
  4. "strconv"
  5. "golang.org/x/text/language"
  6. "golang.org/x/text/message"
  7. "golang.org/x/text/number"
  8. )
  9. // Number
  10. func numberValueFromNumberArgumentList(argumentList []Value) Value {
  11. if len(argumentList) > 0 {
  12. return argumentList[0].numberValue()
  13. }
  14. return intValue(0)
  15. }
  16. func builtinNumber(call FunctionCall) Value {
  17. return numberValueFromNumberArgumentList(call.ArgumentList)
  18. }
  19. func builtinNewNumber(obj *object, argumentList []Value) Value {
  20. return objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList)))
  21. }
  22. func builtinNumberToString(call FunctionCall) Value {
  23. // Will throw a TypeError if ThisObject is not a Number
  24. value := call.thisClassObject(classNumberName).primitiveValue()
  25. radix := 10
  26. radixArgument := call.Argument(0)
  27. if radixArgument.IsDefined() {
  28. integer := toIntegerFloat(radixArgument)
  29. if integer < 2 || integer > 36 {
  30. panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36"))
  31. }
  32. radix = int(integer)
  33. }
  34. if radix == 10 {
  35. return stringValue(value.string())
  36. }
  37. return stringValue(numberToStringRadix(value, radix))
  38. }
  39. func builtinNumberValueOf(call FunctionCall) Value {
  40. return call.thisClassObject(classNumberName).primitiveValue()
  41. }
  42. func builtinNumberToFixed(call FunctionCall) Value {
  43. precision := toIntegerFloat(call.Argument(0))
  44. if 20 < precision || 0 > precision {
  45. panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20"))
  46. }
  47. if call.This.IsNaN() {
  48. return stringValue("NaN")
  49. }
  50. if value := call.This.float64(); math.Abs(value) >= 1e21 {
  51. return stringValue(floatToString(value, 64))
  52. }
  53. return stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64))
  54. }
  55. func builtinNumberToExponential(call FunctionCall) Value {
  56. if call.This.IsNaN() {
  57. return stringValue("NaN")
  58. }
  59. precision := float64(-1)
  60. if value := call.Argument(0); value.IsDefined() {
  61. precision = toIntegerFloat(value)
  62. if 0 > precision {
  63. panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36"))
  64. }
  65. }
  66. return stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64))
  67. }
  68. func builtinNumberToPrecision(call FunctionCall) Value {
  69. if call.This.IsNaN() {
  70. return stringValue("NaN")
  71. }
  72. value := call.Argument(0)
  73. if value.IsUndefined() {
  74. return stringValue(call.This.string())
  75. }
  76. precision := toIntegerFloat(value)
  77. if 1 > precision {
  78. panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1"))
  79. }
  80. return stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64))
  81. }
  82. func builtinNumberIsNaN(call FunctionCall) Value {
  83. if len(call.ArgumentList) < 1 {
  84. return boolValue(false)
  85. }
  86. return boolValue(call.Argument(0).IsNaN())
  87. }
  88. func builtinNumberToLocaleString(call FunctionCall) Value {
  89. value := call.thisClassObject(classNumberName).primitiveValue()
  90. locale := call.Argument(0)
  91. lang := defaultLanguage
  92. if locale.IsDefined() {
  93. lang = language.MustParse(locale.string())
  94. }
  95. p := message.NewPrinter(lang)
  96. return stringValue(p.Sprintf("%v", number.Decimal(value.value)))
  97. }