string.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package goja
  2. import (
  3. "io"
  4. "strconv"
  5. "unicode/utf16"
  6. "unicode/utf8"
  7. )
  8. const (
  9. __proto__ = "__proto__"
  10. )
  11. var (
  12. stringTrue valueString = asciiString("true")
  13. stringFalse valueString = asciiString("false")
  14. stringNull valueString = asciiString("null")
  15. stringUndefined valueString = asciiString("undefined")
  16. stringObjectC valueString = asciiString("object")
  17. stringFunction valueString = asciiString("function")
  18. stringBoolean valueString = asciiString("boolean")
  19. stringString valueString = asciiString("string")
  20. stringSymbol valueString = asciiString("symbol")
  21. stringNumber valueString = asciiString("number")
  22. stringNaN valueString = asciiString("NaN")
  23. stringInfinity = asciiString("Infinity")
  24. stringPlusInfinity = asciiString("+Infinity")
  25. stringNegInfinity = asciiString("-Infinity")
  26. stringEmpty valueString = asciiString("")
  27. stringError valueString = asciiString("Error")
  28. stringTypeError valueString = asciiString("TypeError")
  29. stringReferenceError valueString = asciiString("ReferenceError")
  30. stringSyntaxError valueString = asciiString("SyntaxError")
  31. stringRangeError valueString = asciiString("RangeError")
  32. stringEvalError valueString = asciiString("EvalError")
  33. stringURIError valueString = asciiString("URIError")
  34. stringGoError valueString = asciiString("GoError")
  35. stringObjectNull valueString = asciiString("[object Null]")
  36. stringObjectObject valueString = asciiString("[object Object]")
  37. stringObjectUndefined valueString = asciiString("[object Undefined]")
  38. stringGlobalObject valueString = asciiString("Global Object")
  39. stringInvalidDate valueString = asciiString("Invalid Date")
  40. )
  41. type valueString interface {
  42. Value
  43. charAt(int64) rune
  44. length() int64
  45. concat(valueString) valueString
  46. substring(start, end int64) valueString
  47. compareTo(valueString) int
  48. reader(start int) io.RuneReader
  49. index(valueString, int64) int64
  50. lastIndex(valueString, int64) int64
  51. toLower() valueString
  52. toUpper() valueString
  53. toTrimmedUTF8() string
  54. }
  55. type stringObject struct {
  56. baseObject
  57. value valueString
  58. length int64
  59. lengthProp valueProperty
  60. }
  61. func newUnicodeString(s string) valueString {
  62. return unicodeString(utf16.Encode([]rune(s)))
  63. }
  64. func newStringValue(s string) valueString {
  65. for _, chr := range s {
  66. if chr >= utf8.RuneSelf {
  67. return newUnicodeString(s)
  68. }
  69. }
  70. return asciiString(s)
  71. }
  72. func (s *stringObject) init() {
  73. s.baseObject.init()
  74. s.setLength()
  75. }
  76. func (s *stringObject) setLength() {
  77. if s.value != nil {
  78. s.length = s.value.length()
  79. }
  80. s.lengthProp.value = intToValue(s.length)
  81. s._put("length", &s.lengthProp)
  82. }
  83. func (s *stringObject) getStr(name string, receiver Value) Value {
  84. if i := strToIdx64(name); i >= 0 && i < s.length {
  85. return s._getIdx(i)
  86. }
  87. return s.baseObject.getStr(name, receiver)
  88. }
  89. func (s *stringObject) getIdx(idx valueInt, receiver Value) Value {
  90. i := int64(idx)
  91. if i >= 0 {
  92. if i < s.length {
  93. return s._getIdx(i)
  94. }
  95. return nil
  96. }
  97. return s.baseObject.getStr(idx.String(), receiver)
  98. }
  99. func (s *stringObject) getOwnPropStr(name string) Value {
  100. if i := strToIdx64(name); i >= 0 && i < s.length {
  101. val := s._getIdx(i)
  102. return &valueProperty{
  103. value: val,
  104. enumerable: true,
  105. }
  106. }
  107. return s.baseObject.getOwnPropStr(name)
  108. }
  109. func (s *stringObject) getOwnPropIdx(idx valueInt) Value {
  110. i := int64(idx)
  111. if i >= 0 {
  112. if i < s.length {
  113. val := s._getIdx(i)
  114. return &valueProperty{
  115. value: val,
  116. enumerable: true,
  117. }
  118. }
  119. return nil
  120. }
  121. return s.baseObject.getOwnPropStr(idx.String())
  122. }
  123. func (s *stringObject) _getIdx(idx int64) Value {
  124. return s.value.substring(idx, idx+1)
  125. }
  126. func (s *stringObject) setOwnStr(name string, val Value, throw bool) bool {
  127. if i := strToIdx64(name); i >= 0 && i < s.length {
  128. s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
  129. return false
  130. }
  131. return s.baseObject.setOwnStr(name, val, throw)
  132. }
  133. func (s *stringObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
  134. i := int64(idx)
  135. if i >= 0 && i < s.length {
  136. s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
  137. return false
  138. }
  139. return s.baseObject.setOwnStr(idx.String(), val, throw)
  140. }
  141. func (s *stringObject) setForeignStr(name string, val, receiver Value, throw bool) (bool, bool) {
  142. return s._setForeignStr(name, s.getOwnPropStr(name), val, receiver, throw)
  143. }
  144. func (s *stringObject) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
  145. return s._setForeignIdx(idx, s.getOwnPropIdx(idx), val, receiver, throw)
  146. }
  147. func (s *stringObject) defineOwnPropertyStr(name string, descr PropertyDescriptor, throw bool) bool {
  148. if i := strToIdx64(name); i >= 0 && i < s.length {
  149. s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i)
  150. return false
  151. }
  152. return s.baseObject.defineOwnPropertyStr(name, descr, throw)
  153. }
  154. func (s *stringObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  155. i := int64(idx)
  156. if i >= 0 && i < s.length {
  157. s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i)
  158. return false
  159. }
  160. return s.baseObject.defineOwnPropertyStr(idx.String(), descr, throw)
  161. }
  162. type stringPropIter struct {
  163. str valueString // separate, because obj can be the singleton
  164. obj *stringObject
  165. idx, length int64
  166. }
  167. func (i *stringPropIter) next() (propIterItem, iterNextFunc) {
  168. if i.idx < i.length {
  169. name := strconv.FormatInt(i.idx, 10)
  170. i.idx++
  171. return propIterItem{name: name, enumerable: _ENUM_TRUE}, i.next
  172. }
  173. return i.obj.baseObject.enumerateUnfiltered()()
  174. }
  175. func (s *stringObject) enumerateUnfiltered() iterNextFunc {
  176. return (&stringPropIter{
  177. str: s.value,
  178. obj: s,
  179. length: s.length,
  180. }).next
  181. }
  182. func (s *stringObject) ownKeys(all bool, accum []Value) []Value {
  183. for i := int64(0); i < s.length; i++ {
  184. accum = append(accum, asciiString(strconv.FormatInt(i, 10)))
  185. }
  186. return s.baseObject.ownKeys(all, accum)
  187. }
  188. func (s *stringObject) deleteStr(name string, throw bool) bool {
  189. if i := strToIdx64(name); i >= 0 && i < s.length {
  190. s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
  191. return false
  192. }
  193. return s.baseObject.deleteStr(name, throw)
  194. }
  195. func (s *stringObject) deleteIdx(idx valueInt, throw bool) bool {
  196. i := int64(idx)
  197. if i >= 0 && i < s.length {
  198. s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
  199. return false
  200. }
  201. return s.baseObject.deleteStr(idx.String(), throw)
  202. }
  203. func (s *stringObject) hasOwnPropertyStr(name string) bool {
  204. if i := strToIdx64(name); i >= 0 && i < s.length {
  205. return true
  206. }
  207. return s.baseObject.hasOwnPropertyStr(name)
  208. }
  209. func (s *stringObject) hasOwnPropertyIdx(idx valueInt) bool {
  210. i := int64(idx)
  211. if i >= 0 && i < s.length {
  212. return true
  213. }
  214. return s.baseObject.hasOwnPropertyStr(idx.String())
  215. }