string.go 8.5 KB

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