builtin_global.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. package goja
  2. import (
  3. "errors"
  4. "io"
  5. "math"
  6. "regexp"
  7. "strconv"
  8. "unicode/utf16"
  9. "unicode/utf8"
  10. )
  11. var (
  12. parseFloatRegexp = regexp.MustCompile(`^([+-]?(?:Infinity|[0-9]*\.?[0-9]*(?:[eE][+-]?[0-9]+)?))`)
  13. )
  14. func (r *Runtime) builtin_isNaN(call FunctionCall) Value {
  15. if math.IsNaN(call.Argument(0).ToFloat()) {
  16. return valueTrue
  17. } else {
  18. return valueFalse
  19. }
  20. }
  21. func (r *Runtime) builtin_parseInt(call FunctionCall) Value {
  22. str := call.Argument(0).ToString().toTrimmedUTF8()
  23. radix := int(toInt32(call.Argument(1)))
  24. v, _ := parseInt(str, radix)
  25. return v
  26. }
  27. func (r *Runtime) builtin_parseFloat(call FunctionCall) Value {
  28. m := parseFloatRegexp.FindStringSubmatch(call.Argument(0).ToString().toTrimmedUTF8())
  29. if len(m) == 2 {
  30. if s := m[1]; s != "" && s != "+" && s != "-" {
  31. switch s {
  32. case "+", "-":
  33. case "Infinity", "+Infinity":
  34. return _positiveInf
  35. case "-Infinity":
  36. return _negativeInf
  37. default:
  38. f, err := strconv.ParseFloat(s, 64)
  39. if err == nil || isRangeErr(err) {
  40. return floatToValue(f)
  41. }
  42. }
  43. }
  44. }
  45. return _NaN
  46. }
  47. func (r *Runtime) builtin_isFinite(call FunctionCall) Value {
  48. f := call.Argument(0).ToFloat()
  49. if math.IsNaN(f) || math.IsInf(f, 0) {
  50. return valueFalse
  51. }
  52. return valueTrue
  53. }
  54. func (r *Runtime) _encode(uriString valueString, unescaped *[256]bool) valueString {
  55. reader := uriString.reader(0)
  56. utf8Buf := make([]byte, utf8.UTFMax)
  57. needed := false
  58. l := 0
  59. for {
  60. rn, _, err := reader.ReadRune()
  61. if err != nil {
  62. if err != io.EOF {
  63. panic(r.newError(r.global.URIError, "Malformed URI"))
  64. }
  65. break
  66. }
  67. if rn >= utf8.RuneSelf {
  68. needed = true
  69. l += utf8.EncodeRune(utf8Buf, rn) * 3
  70. } else if !unescaped[rn] {
  71. needed = true
  72. l += 3
  73. } else {
  74. l++
  75. }
  76. }
  77. if !needed {
  78. return uriString
  79. }
  80. buf := make([]byte, l)
  81. i := 0
  82. reader = uriString.reader(0)
  83. for {
  84. rn, _, err := reader.ReadRune()
  85. if err != nil {
  86. break
  87. }
  88. if rn >= utf8.RuneSelf {
  89. n := utf8.EncodeRune(utf8Buf, rn)
  90. for _, b := range utf8Buf[:n] {
  91. buf[i] = '%'
  92. buf[i+1] = "0123456789ABCDEF"[b>>4]
  93. buf[i+2] = "0123456789ABCDEF"[b&15]
  94. i += 3
  95. }
  96. } else if !unescaped[rn] {
  97. buf[i] = '%'
  98. buf[i+1] = "0123456789ABCDEF"[rn>>4]
  99. buf[i+2] = "0123456789ABCDEF"[rn&15]
  100. i += 3
  101. } else {
  102. buf[i] = byte(rn)
  103. i++
  104. }
  105. }
  106. return asciiString(string(buf))
  107. }
  108. func (r *Runtime) _decode(sv valueString, reservedSet *[256]bool) valueString {
  109. s := sv.String()
  110. hexCount := 0
  111. for i := 0; i < len(s); {
  112. switch s[i] {
  113. case '%':
  114. if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
  115. panic(r.newError(r.global.URIError, "Malformed URI"))
  116. }
  117. c := unhex(s[i+1])<<4 | unhex(s[i+2])
  118. if !reservedSet[c] {
  119. hexCount++
  120. }
  121. i += 3
  122. default:
  123. i++
  124. }
  125. }
  126. if hexCount == 0 {
  127. return sv
  128. }
  129. t := make([]byte, len(s)-hexCount*2)
  130. j := 0
  131. isUnicode := false
  132. for i := 0; i < len(s); {
  133. ch := s[i]
  134. switch ch {
  135. case '%':
  136. c := unhex(s[i+1])<<4 | unhex(s[i+2])
  137. if reservedSet[c] {
  138. t[j] = s[i]
  139. t[j+1] = s[i+1]
  140. t[j+2] = s[i+2]
  141. j += 3
  142. } else {
  143. t[j] = c
  144. if c >= utf8.RuneSelf {
  145. isUnicode = true
  146. }
  147. j++
  148. }
  149. i += 3
  150. default:
  151. if ch >= utf8.RuneSelf {
  152. isUnicode = true
  153. }
  154. t[j] = ch
  155. j++
  156. i++
  157. }
  158. }
  159. if !isUnicode {
  160. return asciiString(t)
  161. }
  162. us := make([]rune, 0, len(s))
  163. for len(t) > 0 {
  164. rn, size := utf8.DecodeRune(t)
  165. if rn == utf8.RuneError {
  166. if size != 3 || t[0] != 0xef || t[1] != 0xbf || t[2] != 0xbd {
  167. panic(r.newError(r.global.URIError, "Malformed URI"))
  168. }
  169. }
  170. us = append(us, rn)
  171. t = t[size:]
  172. }
  173. return unicodeString(utf16.Encode(us))
  174. }
  175. func ishex(c byte) bool {
  176. switch {
  177. case '0' <= c && c <= '9':
  178. return true
  179. case 'a' <= c && c <= 'f':
  180. return true
  181. case 'A' <= c && c <= 'F':
  182. return true
  183. }
  184. return false
  185. }
  186. func unhex(c byte) byte {
  187. switch {
  188. case '0' <= c && c <= '9':
  189. return c - '0'
  190. case 'a' <= c && c <= 'f':
  191. return c - 'a' + 10
  192. case 'A' <= c && c <= 'F':
  193. return c - 'A' + 10
  194. }
  195. return 0
  196. }
  197. func (r *Runtime) builtin_decodeURI(call FunctionCall) Value {
  198. uriString := call.Argument(0).ToString()
  199. return r._decode(uriString, &uriReservedHash)
  200. }
  201. func (r *Runtime) builtin_decodeURIComponent(call FunctionCall) Value {
  202. uriString := call.Argument(0).ToString()
  203. return r._decode(uriString, &emptyEscapeSet)
  204. }
  205. func (r *Runtime) builtin_encodeURI(call FunctionCall) Value {
  206. uriString := call.Argument(0).ToString()
  207. return r._encode(uriString, &uriReservedUnescapedHash)
  208. }
  209. func (r *Runtime) builtin_encodeURIComponent(call FunctionCall) Value {
  210. uriString := call.Argument(0).ToString()
  211. return r._encode(uriString, &uriUnescaped)
  212. }
  213. func (r *Runtime) initGlobalObject() {
  214. o := r.globalObject.self
  215. o._putProp("NaN", _NaN, false, false, false)
  216. o._putProp("undefined", _undefined, false, false, false)
  217. o._putProp("Infinity", _positiveInf, false, false, false)
  218. o._putProp("isNaN", r.newNativeFunc(r.builtin_isNaN, nil, "isNaN", nil, 1), true, false, true)
  219. o._putProp("parseInt", r.newNativeFunc(r.builtin_parseInt, nil, "parseInt", nil, 2), true, false, true)
  220. o._putProp("parseFloat", r.newNativeFunc(r.builtin_parseFloat, nil, "parseFloat", nil, 1), true, false, true)
  221. o._putProp("isFinite", r.newNativeFunc(r.builtin_isFinite, nil, "isFinite", nil, 1), true, false, true)
  222. o._putProp("decodeURI", r.newNativeFunc(r.builtin_decodeURI, nil, "decodeURI", nil, 1), true, false, true)
  223. o._putProp("decodeURIComponent", r.newNativeFunc(r.builtin_decodeURIComponent, nil, "decodeURIComponent", nil, 1), true, false, true)
  224. o._putProp("encodeURI", r.newNativeFunc(r.builtin_encodeURI, nil, "encodeURI", nil, 1), true, false, true)
  225. o._putProp("encodeURIComponent", r.newNativeFunc(r.builtin_encodeURIComponent, nil, "encodeURIComponent", nil, 1), true, false, true)
  226. o._putProp("toString", r.newNativeFunc(func(FunctionCall) Value {
  227. return stringGlobalObject
  228. }, nil, "toString", nil, 0), false, false, false)
  229. // TODO: Annex B
  230. }
  231. func digitVal(d byte) int {
  232. var v byte
  233. switch {
  234. case '0' <= d && d <= '9':
  235. v = d - '0'
  236. case 'a' <= d && d <= 'z':
  237. v = d - 'a' + 10
  238. case 'A' <= d && d <= 'Z':
  239. v = d - 'A' + 10
  240. default:
  241. return 36
  242. }
  243. return int(v)
  244. }
  245. // ECMAScript compatible version of strconv.ParseInt
  246. func parseInt(s string, base int) (Value, error) {
  247. var n int64
  248. var err error
  249. var cutoff, maxVal int64
  250. var sign bool
  251. i := 0
  252. if len(s) < 1 {
  253. err = strconv.ErrSyntax
  254. goto Error
  255. }
  256. switch s[0] {
  257. case '-':
  258. sign = true
  259. s = s[1:]
  260. case '+':
  261. s = s[1:]
  262. }
  263. if len(s) < 1 {
  264. err = strconv.ErrSyntax
  265. goto Error
  266. }
  267. // Look for hex prefix.
  268. if s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
  269. if base == 0 || base == 16 {
  270. base = 16
  271. s = s[2:]
  272. }
  273. }
  274. switch {
  275. case len(s) < 1:
  276. err = strconv.ErrSyntax
  277. goto Error
  278. case 2 <= base && base <= 36:
  279. // valid base; nothing to do
  280. case base == 0:
  281. // Look for hex prefix.
  282. switch {
  283. case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
  284. if len(s) < 3 {
  285. err = strconv.ErrSyntax
  286. goto Error
  287. }
  288. base = 16
  289. s = s[2:]
  290. default:
  291. base = 10
  292. }
  293. default:
  294. err = errors.New("invalid base " + strconv.Itoa(base))
  295. goto Error
  296. }
  297. // Cutoff is the smallest number such that cutoff*base > maxInt64.
  298. // Use compile-time constants for common cases.
  299. switch base {
  300. case 10:
  301. cutoff = math.MaxInt64/10 + 1
  302. case 16:
  303. cutoff = math.MaxInt64/16 + 1
  304. default:
  305. cutoff = math.MaxInt64/int64(base) + 1
  306. }
  307. maxVal = math.MaxInt64
  308. for ; i < len(s); i++ {
  309. if n >= cutoff {
  310. // n*base overflows
  311. return parseLargeInt(float64(n), s[i:], base, sign)
  312. }
  313. v := digitVal(s[i])
  314. if v >= base {
  315. break
  316. }
  317. n *= int64(base)
  318. n1 := n + int64(v)
  319. if n1 < n || n1 > maxVal {
  320. // n+v overflows
  321. return parseLargeInt(float64(n)+float64(v), s[i+1:], base, sign)
  322. }
  323. n = n1
  324. }
  325. if i == 0 {
  326. err = strconv.ErrSyntax
  327. goto Error
  328. }
  329. if sign {
  330. n = -n
  331. }
  332. return intToValue(n), nil
  333. Error:
  334. return _NaN, err
  335. }
  336. func parseLargeInt(n float64, s string, base int, sign bool) (Value, error) {
  337. i := 0
  338. b := float64(base)
  339. for ; i < len(s); i++ {
  340. v := digitVal(s[i])
  341. if v >= base {
  342. break
  343. }
  344. n = n*b + float64(v)
  345. }
  346. if sign {
  347. n = -n
  348. }
  349. // We know it can't be represented as int, so use valueFloat instead of floatToValue
  350. return valueFloat(n), nil
  351. }
  352. var (
  353. uriUnescaped [256]bool
  354. uriReserved [256]bool
  355. uriReservedHash [256]bool
  356. uriReservedUnescapedHash [256]bool
  357. emptyEscapeSet [256]bool
  358. )
  359. func init() {
  360. for _, c := range "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()" {
  361. uriUnescaped[c] = true
  362. }
  363. for _, c := range ";/?:@&=+$," {
  364. uriReserved[c] = true
  365. }
  366. for i := 0; i < 256; i++ {
  367. if uriUnescaped[i] || uriReserved[i] {
  368. uriReservedUnescapedHash[i] = true
  369. }
  370. uriReservedHash[i] = uriReserved[i]
  371. }
  372. uriReservedUnescapedHash['#'] = true
  373. uriReservedHash['#'] = true
  374. }