string.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. package goja
  2. import (
  3. "io"
  4. "strconv"
  5. "strings"
  6. "unicode/utf16"
  7. "unicode/utf8"
  8. "github.com/dop251/goja/unistring"
  9. )
  10. const (
  11. __proto__ = "__proto__"
  12. )
  13. var (
  14. stringTrue valueString = asciiString("true")
  15. stringFalse valueString = asciiString("false")
  16. stringNull valueString = asciiString("null")
  17. stringUndefined valueString = asciiString("undefined")
  18. stringObjectC valueString = asciiString("object")
  19. stringFunction valueString = asciiString("function")
  20. stringBoolean valueString = asciiString("boolean")
  21. stringString valueString = asciiString("string")
  22. stringSymbol valueString = asciiString("symbol")
  23. stringNumber valueString = asciiString("number")
  24. stringNaN valueString = asciiString("NaN")
  25. stringInfinity = asciiString("Infinity")
  26. stringPlusInfinity = asciiString("+Infinity")
  27. stringNegInfinity = asciiString("-Infinity")
  28. stringBound_ valueString = asciiString("bound ")
  29. stringEmpty valueString = asciiString("")
  30. stringError valueString = asciiString("Error")
  31. stringAggregateError valueString = asciiString("AggregateError")
  32. stringTypeError valueString = asciiString("TypeError")
  33. stringReferenceError valueString = asciiString("ReferenceError")
  34. stringSyntaxError valueString = asciiString("SyntaxError")
  35. stringRangeError valueString = asciiString("RangeError")
  36. stringEvalError valueString = asciiString("EvalError")
  37. stringURIError valueString = asciiString("URIError")
  38. stringGoError valueString = asciiString("GoError")
  39. stringObjectNull valueString = asciiString("[object Null]")
  40. stringObjectObject valueString = asciiString("[object Object]")
  41. stringObjectUndefined valueString = asciiString("[object Undefined]")
  42. stringInvalidDate valueString = asciiString("Invalid Date")
  43. )
  44. type valueString interface {
  45. Value
  46. charAt(int) rune
  47. length() int
  48. concat(valueString) valueString
  49. substring(start, end int) valueString
  50. compareTo(valueString) int
  51. reader(start int) io.RuneReader
  52. utf16Reader(start int) io.RuneReader
  53. utf16Runes() []rune
  54. index(valueString, int) int
  55. lastIndex(valueString, int) int
  56. toLower() valueString
  57. toUpper() valueString
  58. toTrimmedUTF8() string
  59. }
  60. type stringIterObject struct {
  61. baseObject
  62. reader io.RuneReader
  63. }
  64. func isUTF16FirstSurrogate(r rune) bool {
  65. return r >= 0xD800 && r <= 0xDBFF
  66. }
  67. func isUTF16SecondSurrogate(r rune) bool {
  68. return r >= 0xDC00 && r <= 0xDFFF
  69. }
  70. func (si *stringIterObject) next() Value {
  71. if si.reader == nil {
  72. return si.val.runtime.createIterResultObject(_undefined, true)
  73. }
  74. r, _, err := si.reader.ReadRune()
  75. if err == io.EOF {
  76. si.reader = nil
  77. return si.val.runtime.createIterResultObject(_undefined, true)
  78. }
  79. return si.val.runtime.createIterResultObject(stringFromRune(r), false)
  80. }
  81. func stringFromRune(r rune) valueString {
  82. if r < utf8.RuneSelf {
  83. var sb strings.Builder
  84. sb.Grow(1)
  85. sb.WriteByte(byte(r))
  86. return asciiString(sb.String())
  87. }
  88. var sb unicodeStringBuilder
  89. if r <= 0xFFFF {
  90. sb.Grow(1)
  91. } else {
  92. sb.Grow(2)
  93. }
  94. sb.WriteRune(r)
  95. return sb.String()
  96. }
  97. func (r *Runtime) createStringIterator(s valueString) Value {
  98. o := &Object{runtime: r}
  99. si := &stringIterObject{
  100. reader: &lenientUtf16Decoder{utf16Reader: s.utf16Reader(0)},
  101. }
  102. si.class = classStringIterator
  103. si.val = o
  104. si.extensible = true
  105. o.self = si
  106. si.prototype = r.global.StringIteratorPrototype
  107. si.init()
  108. return o
  109. }
  110. type stringObject struct {
  111. baseObject
  112. value valueString
  113. length int
  114. lengthProp valueProperty
  115. }
  116. func newStringValue(s string) valueString {
  117. utf16Size := 0
  118. ascii := true
  119. for _, chr := range s {
  120. utf16Size++
  121. if chr >= utf8.RuneSelf {
  122. ascii = false
  123. if chr > 0xFFFF {
  124. utf16Size++
  125. }
  126. }
  127. }
  128. if ascii {
  129. return asciiString(s)
  130. }
  131. buf := make([]uint16, utf16Size+1)
  132. buf[0] = unistring.BOM
  133. c := 1
  134. for _, chr := range s {
  135. if chr <= 0xFFFF {
  136. buf[c] = uint16(chr)
  137. } else {
  138. first, second := utf16.EncodeRune(chr)
  139. buf[c] = uint16(first)
  140. c++
  141. buf[c] = uint16(second)
  142. }
  143. c++
  144. }
  145. return unicodeString(buf)
  146. }
  147. func stringValueFromRaw(raw unistring.String) valueString {
  148. if b := raw.AsUtf16(); b != nil {
  149. return unicodeString(b)
  150. }
  151. return asciiString(raw)
  152. }
  153. func (s *stringObject) init() {
  154. s.baseObject.init()
  155. s.setLength()
  156. }
  157. func (s *stringObject) setLength() {
  158. if s.value != nil {
  159. s.length = s.value.length()
  160. }
  161. s.lengthProp.value = intToValue(int64(s.length))
  162. s._put("length", &s.lengthProp)
  163. }
  164. func (s *stringObject) getStr(name unistring.String, receiver Value) Value {
  165. if i := strToGoIdx(name); i >= 0 && i < s.length {
  166. return s._getIdx(i)
  167. }
  168. return s.baseObject.getStr(name, receiver)
  169. }
  170. func (s *stringObject) getIdx(idx valueInt, receiver Value) Value {
  171. i := int(idx)
  172. if i >= 0 && i < s.length {
  173. return s._getIdx(i)
  174. }
  175. return s.baseObject.getStr(idx.string(), receiver)
  176. }
  177. func (s *stringObject) getOwnPropStr(name unistring.String) Value {
  178. if i := strToGoIdx(name); i >= 0 && i < s.length {
  179. val := s._getIdx(i)
  180. return &valueProperty{
  181. value: val,
  182. enumerable: true,
  183. }
  184. }
  185. return s.baseObject.getOwnPropStr(name)
  186. }
  187. func (s *stringObject) getOwnPropIdx(idx valueInt) Value {
  188. i := int64(idx)
  189. if i >= 0 {
  190. if i < int64(s.length) {
  191. val := s._getIdx(int(i))
  192. return &valueProperty{
  193. value: val,
  194. enumerable: true,
  195. }
  196. }
  197. return nil
  198. }
  199. return s.baseObject.getOwnPropStr(idx.string())
  200. }
  201. func (s *stringObject) _getIdx(idx int) Value {
  202. return s.value.substring(idx, idx+1)
  203. }
  204. func (s *stringObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
  205. if i := strToGoIdx(name); i >= 0 && i < s.length {
  206. s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
  207. return false
  208. }
  209. return s.baseObject.setOwnStr(name, val, throw)
  210. }
  211. func (s *stringObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
  212. i := int64(idx)
  213. if i >= 0 && i < int64(s.length) {
  214. s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
  215. return false
  216. }
  217. return s.baseObject.setOwnStr(idx.string(), val, throw)
  218. }
  219. func (s *stringObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
  220. return s._setForeignStr(name, s.getOwnPropStr(name), val, receiver, throw)
  221. }
  222. func (s *stringObject) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
  223. return s._setForeignIdx(idx, s.getOwnPropIdx(idx), val, receiver, throw)
  224. }
  225. func (s *stringObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
  226. if i := strToGoIdx(name); i >= 0 && i < s.length {
  227. _, ok := s._defineOwnProperty(name, &valueProperty{enumerable: true}, descr, throw)
  228. return ok
  229. }
  230. return s.baseObject.defineOwnPropertyStr(name, descr, throw)
  231. }
  232. func (s *stringObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
  233. i := int64(idx)
  234. if i >= 0 && i < int64(s.length) {
  235. s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i)
  236. return false
  237. }
  238. return s.baseObject.defineOwnPropertyStr(idx.string(), descr, throw)
  239. }
  240. type stringPropIter struct {
  241. str valueString // separate, because obj can be the singleton
  242. obj *stringObject
  243. idx, length int
  244. }
  245. func (i *stringPropIter) next() (propIterItem, iterNextFunc) {
  246. if i.idx < i.length {
  247. name := strconv.Itoa(i.idx)
  248. i.idx++
  249. return propIterItem{name: asciiString(name), enumerable: _ENUM_TRUE}, i.next
  250. }
  251. return i.obj.baseObject.iterateStringKeys()()
  252. }
  253. func (s *stringObject) iterateStringKeys() iterNextFunc {
  254. return (&stringPropIter{
  255. str: s.value,
  256. obj: s,
  257. length: s.length,
  258. }).next
  259. }
  260. func (s *stringObject) stringKeys(all bool, accum []Value) []Value {
  261. for i := 0; i < s.length; i++ {
  262. accum = append(accum, asciiString(strconv.Itoa(i)))
  263. }
  264. return s.baseObject.stringKeys(all, accum)
  265. }
  266. func (s *stringObject) deleteStr(name unistring.String, throw bool) bool {
  267. if i := strToGoIdx(name); i >= 0 && i < s.length {
  268. s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
  269. return false
  270. }
  271. return s.baseObject.deleteStr(name, throw)
  272. }
  273. func (s *stringObject) deleteIdx(idx valueInt, throw bool) bool {
  274. i := int64(idx)
  275. if i >= 0 && i < int64(s.length) {
  276. s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
  277. return false
  278. }
  279. return s.baseObject.deleteStr(idx.string(), throw)
  280. }
  281. func (s *stringObject) hasOwnPropertyStr(name unistring.String) bool {
  282. if i := strToGoIdx(name); i >= 0 && i < s.length {
  283. return true
  284. }
  285. return s.baseObject.hasOwnPropertyStr(name)
  286. }
  287. func (s *stringObject) hasOwnPropertyIdx(idx valueInt) bool {
  288. i := int64(idx)
  289. if i >= 0 && i < int64(s.length) {
  290. return true
  291. }
  292. return s.baseObject.hasOwnPropertyStr(idx.string())
  293. }