builtin_global.go 15 KB

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