builtin_global.go 11 KB

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