string.go 6.0 KB

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