otto_.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package otto
  2. import (
  3. "fmt"
  4. "regexp"
  5. runtime_ "runtime"
  6. "strconv"
  7. )
  8. var isIdentifier_Regexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`)
  9. func isIdentifier(string_ string) bool {
  10. return isIdentifier_Regexp.MatchString(string_)
  11. }
  12. func (self *_runtime) toValueArray(arguments ...interface{}) []Value {
  13. length := len(arguments)
  14. if length == 1 {
  15. if valueArray, ok := arguments[0].([]Value); ok {
  16. return valueArray
  17. }
  18. return []Value{self.toValue(arguments[0])}
  19. }
  20. valueArray := make([]Value, length)
  21. for index, value := range arguments {
  22. valueArray[index] = self.toValue(value)
  23. }
  24. return valueArray
  25. }
  26. func stringToArrayIndex(name string) int64 {
  27. index, err := strconv.ParseInt(name, 10, 64)
  28. if err != nil {
  29. return -1
  30. }
  31. if index < 0 {
  32. return -1
  33. }
  34. if index >= maxUint32 {
  35. // The value 2^32 (or above) is not a valid index because
  36. // you cannot store a uint32 length for an index of uint32
  37. return -1
  38. }
  39. return index
  40. }
  41. func isUint32(value int64) bool {
  42. return value >= 0 && value <= maxUint32
  43. }
  44. func arrayIndexToString(index int64) string {
  45. return strconv.FormatInt(index, 10)
  46. }
  47. func valueOfArrayIndex(array []Value, index int) Value {
  48. value, _ := getValueOfArrayIndex(array, index)
  49. return value
  50. }
  51. func getValueOfArrayIndex(array []Value, index int) (Value, bool) {
  52. if index >= 0 && index < len(array) {
  53. value := array[index]
  54. if !value.isEmpty() {
  55. return value, true
  56. }
  57. }
  58. return Value{}, false
  59. }
  60. // A range index can be anything from 0 up to length. It is NOT safe to use as an index
  61. // to an array, but is useful for slicing and in some ECMA algorithms.
  62. func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int64 {
  63. index := indexValue.number().int64
  64. if negativeIsZero {
  65. if index < 0 {
  66. index = 0
  67. }
  68. // minimum(index, length)
  69. if index >= length {
  70. index = length
  71. }
  72. return index
  73. }
  74. if index < 0 {
  75. index += length
  76. if index < 0 {
  77. index = 0
  78. }
  79. } else {
  80. if index > length {
  81. index = length
  82. }
  83. }
  84. return index
  85. }
  86. func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) {
  87. start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero)
  88. if len(array) == 1 {
  89. // If there is only the start argument, then end = size
  90. end = size
  91. return
  92. }
  93. // Assuming the argument is undefined...
  94. end = size
  95. endValue := valueOfArrayIndex(array, 1)
  96. if !endValue.IsUndefined() {
  97. // Which it is not, so get the value as an array index
  98. end = valueToRangeIndex(endValue, size, negativeIsZero)
  99. }
  100. return
  101. }
  102. func rangeStartLength(source []Value, size int64) (start, length int64) {
  103. start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false)
  104. // Assume the second argument is missing or undefined
  105. length = int64(size)
  106. if len(source) == 1 {
  107. // If there is only the start argument, then length = size
  108. return
  109. }
  110. lengthValue := valueOfArrayIndex(source, 1)
  111. if !lengthValue.IsUndefined() {
  112. // Which it is not, so get the value as an array index
  113. length = lengthValue.number().int64
  114. }
  115. return
  116. }
  117. func hereBeDragons(arguments ...interface{}) string {
  118. pc, _, _, _ := runtime_.Caller(1) // nolint: dogsled
  119. name := runtime_.FuncForPC(pc).Name()
  120. message := fmt.Sprintf("Here be dragons -- %s", name)
  121. if len(arguments) > 0 {
  122. message += ": "
  123. argument0 := fmt.Sprintf("%s", arguments[0])
  124. if len(arguments) == 1 {
  125. message += argument0
  126. } else {
  127. message += fmt.Sprintf(argument0, arguments[1:]...)
  128. }
  129. } else {
  130. message += "."
  131. }
  132. return message
  133. }