builtin_json.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package goja
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "strings"
  6. )
  7. var hex = "0123456789abcdef"
  8. func (r *Runtime) builtinJSON_parse(call FunctionCall) Value {
  9. var reviver func(FunctionCall) Value
  10. if arg1 := call.Argument(1); arg1 != _undefined {
  11. reviver, _ = arg1.ToObject(r).self.assertCallable()
  12. }
  13. var root interface{}
  14. err := json.Unmarshal([]byte(call.Argument(0).String()), &root)
  15. if err != nil {
  16. panic(r.newError(r.global.SyntaxError, err.Error()))
  17. }
  18. value, exists := r.builtinJSON_parseWalk(root)
  19. if !exists {
  20. value = _undefined
  21. }
  22. if reviver != nil {
  23. root := r.NewObject()
  24. root.self.putStr("", value, false)
  25. return r.builtinJSON_reviveWalk(reviver, root, stringEmpty)
  26. }
  27. return value
  28. }
  29. func (r *Runtime) builtinJSON_parseWalk(rawValue interface{}) (Value, bool) {
  30. switch value := rawValue.(type) {
  31. case nil:
  32. return _null, true
  33. case bool:
  34. if value {
  35. return valueTrue, true
  36. } else {
  37. return valueFalse, true
  38. }
  39. case string:
  40. return newStringValue(value), true
  41. case float64:
  42. return floatToValue(value), true
  43. case []interface{}:
  44. arrayValue := make([]Value, len(value))
  45. for index, rawValue := range value {
  46. if value, exists := r.builtinJSON_parseWalk(rawValue); exists {
  47. arrayValue[index] = value
  48. }
  49. }
  50. return r.newArrayValues(arrayValue), true
  51. case map[string]interface{}:
  52. object := r.NewObject()
  53. for name, rawValue := range value {
  54. if value, exists := r.builtinJSON_parseWalk(rawValue); exists {
  55. if name == "__proto__" {
  56. descr := r.NewObject().self
  57. descr.putStr("value", value, false)
  58. descr.putStr("writable", valueTrue, false)
  59. descr.putStr("enumerable", valueTrue, false)
  60. descr.putStr("configurable", valueTrue, false)
  61. object.self.defineOwnProperty(string__proto__, descr, false)
  62. } else {
  63. object.self.putStr(name, value, false)
  64. }
  65. }
  66. }
  67. return object, true
  68. }
  69. return _undefined, false
  70. }
  71. func isArray(object *Object) bool {
  72. switch object.self.className() {
  73. case classArray:
  74. return true
  75. default:
  76. return false
  77. }
  78. }
  79. func (r *Runtime) builtinJSON_reviveWalk(reviver func(FunctionCall) Value, holder *Object, name Value) Value {
  80. value := holder.self.get(name)
  81. if value == nil {
  82. value = _undefined
  83. }
  84. if object := value.(*Object); object != nil {
  85. if isArray(object) {
  86. length := object.self.getStr("length").ToInteger()
  87. for index := int64(0); index < length; index++ {
  88. name := intToValue(index)
  89. value := r.builtinJSON_reviveWalk(reviver, object, name)
  90. if value == _undefined {
  91. object.self.delete(name, false)
  92. } else {
  93. object.self.put(name, value, false)
  94. }
  95. }
  96. } else {
  97. for item, f := object.self.enumerate(false, false)(); f != nil; item, f = f() {
  98. value := r.builtinJSON_reviveWalk(reviver, object, name)
  99. if value == _undefined {
  100. object.self.deleteStr(item.name, false)
  101. } else {
  102. object.self.putStr(item.name, value, false)
  103. }
  104. }
  105. }
  106. }
  107. return reviver(FunctionCall{
  108. This: holder,
  109. Arguments: []Value{name, value},
  110. })
  111. }
  112. type _builtinJSON_stringifyContext struct {
  113. r *Runtime
  114. stack []*Object
  115. propertyList []Value
  116. replacerFunction func(FunctionCall) Value
  117. gap, indent string
  118. buf bytes.Buffer
  119. }
  120. func (r *Runtime) builtinJSON_stringify(call FunctionCall) Value {
  121. ctx := _builtinJSON_stringifyContext{
  122. r: r,
  123. }
  124. replacer, _ := call.Argument(1).(*Object)
  125. if replacer != nil {
  126. if isArray(replacer) {
  127. length := replacer.self.getStr("length").ToInteger()
  128. seen := map[string]bool{}
  129. propertyList := make([]Value, length)
  130. length = 0
  131. for index := range propertyList {
  132. var name string
  133. value := replacer.self.get(intToValue(int64(index)))
  134. if s, ok := value.assertString(); ok {
  135. name = s.String()
  136. } else if _, ok := value.assertInt(); ok {
  137. name = value.String()
  138. } else if _, ok := value.assertFloat(); ok {
  139. name = value.String()
  140. } else if o, ok := value.(*Object); ok {
  141. switch o.self.className() {
  142. case classNumber, classString:
  143. name = value.String()
  144. }
  145. }
  146. if seen[name] {
  147. continue
  148. }
  149. seen[name] = true
  150. length += 1
  151. propertyList[index] = newStringValue(name)
  152. }
  153. ctx.propertyList = propertyList[0:length]
  154. } else if c, ok := replacer.self.assertCallable(); ok {
  155. ctx.replacerFunction = c
  156. }
  157. }
  158. if spaceValue := call.Argument(2); spaceValue != _undefined {
  159. if o, ok := spaceValue.(*Object); ok {
  160. switch o := o.self.(type) {
  161. case *primitiveValueObject:
  162. spaceValue = o.pValue
  163. case *stringObject:
  164. spaceValue = o.value
  165. }
  166. }
  167. isNum := false
  168. var num int64
  169. num, isNum = spaceValue.assertInt()
  170. if !isNum {
  171. if f, ok := spaceValue.assertFloat(); ok {
  172. num = int64(f)
  173. isNum = true
  174. }
  175. }
  176. if isNum {
  177. if num > 0 {
  178. if num > 10 {
  179. num = 10
  180. }
  181. ctx.gap = strings.Repeat(" ", int(num))
  182. }
  183. } else {
  184. if s, ok := spaceValue.assertString(); ok {
  185. str := s.String()
  186. if len(str) > 10 {
  187. ctx.gap = str[:10]
  188. } else {
  189. ctx.gap = str
  190. }
  191. }
  192. }
  193. }
  194. holder := r.NewObject()
  195. holder.self.putStr("", call.Argument(0), false)
  196. if ctx.str(stringEmpty, holder) {
  197. return newStringValue(ctx.buf.String())
  198. }
  199. return _undefined
  200. }
  201. func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool {
  202. value := holder.self.get(key)
  203. if value == nil {
  204. value = _undefined
  205. }
  206. if object, ok := value.(*Object); ok {
  207. if toJSON, ok := object.self.getStr("toJSON").(*Object); ok {
  208. if c, ok := toJSON.self.assertCallable(); ok {
  209. value = c(FunctionCall{
  210. This: value,
  211. Arguments: []Value{key},
  212. })
  213. }
  214. } /*else {
  215. // If the object is a GoStruct or something that implements json.Marshaler
  216. if object.objectClass.marshalJSON != nil {
  217. marshaler := object.objectClass.marshalJSON(object)
  218. if marshaler != nil {
  219. return marshaler, true
  220. }
  221. }
  222. }*/
  223. }
  224. if ctx.replacerFunction != nil {
  225. value = ctx.replacerFunction(FunctionCall{
  226. This: holder,
  227. Arguments: []Value{key, value},
  228. })
  229. }
  230. if o, ok := value.(*Object); ok {
  231. switch o1 := o.self.(type) {
  232. case *primitiveValueObject:
  233. value = o1.pValue
  234. case *stringObject:
  235. value = o1.value
  236. case *objectGoReflect:
  237. switch o.self.className() {
  238. case classNumber:
  239. value = o1.toPrimitiveNumber()
  240. case classString:
  241. value = o1.toPrimitiveString()
  242. case classBoolean:
  243. if o.ToInteger() != 0 {
  244. value = valueTrue
  245. } else {
  246. value = valueFalse
  247. }
  248. }
  249. }
  250. }
  251. switch value1 := value.(type) {
  252. case valueBool:
  253. if value1 {
  254. ctx.buf.WriteString("true")
  255. } else {
  256. ctx.buf.WriteString("false")
  257. }
  258. case valueString:
  259. ctx.quote(value1)
  260. case valueInt, valueFloat:
  261. ctx.buf.WriteString(value.String())
  262. case valueNull:
  263. ctx.buf.WriteString("null")
  264. case *Object:
  265. for _, object := range ctx.stack {
  266. if value1 == object {
  267. ctx.r.typeErrorResult(true, "Converting circular structure to JSON")
  268. }
  269. }
  270. ctx.stack = append(ctx.stack, value1)
  271. defer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }()
  272. if _, ok := value1.self.assertCallable(); !ok {
  273. if isArray(value1) {
  274. ctx.ja(value1)
  275. } else {
  276. ctx.jo(value1)
  277. }
  278. } else {
  279. return false
  280. }
  281. default:
  282. return false
  283. }
  284. return true
  285. }
  286. func (ctx *_builtinJSON_stringifyContext) ja(array *Object) {
  287. var stepback string
  288. if ctx.gap != "" {
  289. stepback = ctx.indent
  290. ctx.indent += ctx.gap
  291. }
  292. length := array.self.getStr("length").ToInteger()
  293. if length == 0 {
  294. ctx.buf.WriteString("[]")
  295. return
  296. }
  297. ctx.buf.WriteByte('[')
  298. var separator string
  299. if ctx.gap != "" {
  300. ctx.buf.WriteByte('\n')
  301. ctx.buf.WriteString(ctx.indent)
  302. separator = ",\n" + ctx.indent
  303. } else {
  304. separator = ","
  305. }
  306. for i := int64(0); i < length; i++ {
  307. if !ctx.str(intToValue(i), array) {
  308. ctx.buf.WriteString("null")
  309. }
  310. if i < length-1 {
  311. ctx.buf.WriteString(separator)
  312. }
  313. }
  314. if ctx.gap != "" {
  315. ctx.buf.WriteByte('\n')
  316. ctx.buf.WriteString(stepback)
  317. ctx.indent = stepback
  318. }
  319. ctx.buf.WriteByte(']')
  320. }
  321. func (ctx *_builtinJSON_stringifyContext) jo(object *Object) {
  322. var stepback string
  323. if ctx.gap != "" {
  324. stepback = ctx.indent
  325. ctx.indent += ctx.gap
  326. }
  327. ctx.buf.WriteByte('{')
  328. mark := ctx.buf.Len()
  329. var separator string
  330. if ctx.gap != "" {
  331. ctx.buf.WriteByte('\n')
  332. ctx.buf.WriteString(ctx.indent)
  333. separator = ",\n" + ctx.indent
  334. } else {
  335. separator = ","
  336. }
  337. var props []Value
  338. if ctx.propertyList == nil {
  339. for item, f := object.self.enumerate(false, false)(); f != nil; item, f = f() {
  340. props = append(props, newStringValue(item.name))
  341. }
  342. } else {
  343. props = ctx.propertyList
  344. }
  345. empty := true
  346. for _, name := range props {
  347. off := ctx.buf.Len()
  348. if !empty {
  349. ctx.buf.WriteString(separator)
  350. }
  351. ctx.quote(name.ToString())
  352. if ctx.gap != "" {
  353. ctx.buf.WriteString(": ")
  354. } else {
  355. ctx.buf.WriteByte(':')
  356. }
  357. if ctx.str(name, object) {
  358. if empty {
  359. empty = false
  360. }
  361. } else {
  362. ctx.buf.Truncate(off)
  363. }
  364. }
  365. if empty {
  366. ctx.buf.Truncate(mark)
  367. } else {
  368. if ctx.gap != "" {
  369. ctx.buf.WriteByte('\n')
  370. ctx.buf.WriteString(stepback)
  371. ctx.indent = stepback
  372. }
  373. }
  374. ctx.buf.WriteByte('}')
  375. }
  376. func (ctx *_builtinJSON_stringifyContext) quote(str valueString) {
  377. ctx.buf.WriteByte('"')
  378. reader := str.reader(0)
  379. for {
  380. r, _, err := reader.ReadRune()
  381. if err != nil {
  382. break
  383. }
  384. switch r {
  385. case '"', '\\':
  386. ctx.buf.WriteByte('\\')
  387. ctx.buf.WriteByte(byte(r))
  388. case 0x08:
  389. ctx.buf.WriteString(`\b`)
  390. case 0x09:
  391. ctx.buf.WriteString(`\t`)
  392. case 0x0A:
  393. ctx.buf.WriteString(`\n`)
  394. case 0x0C:
  395. ctx.buf.WriteString(`\f`)
  396. case 0x0D:
  397. ctx.buf.WriteString(`\r`)
  398. default:
  399. if r < 0x20 {
  400. ctx.buf.WriteString(`\u00`)
  401. ctx.buf.WriteByte(hex[r >> 4])
  402. ctx.buf.WriteByte(hex[r & 0xF])
  403. } else {
  404. ctx.buf.WriteRune(r)
  405. }
  406. }
  407. }
  408. ctx.buf.WriteByte('"')
  409. }
  410. func (r *Runtime) initJSON() {
  411. JSON := r.newBaseObject(r.global.ObjectPrototype, "JSON")
  412. JSON._putProp("parse", r.newNativeFunc(r.builtinJSON_parse, nil, "parse", nil, 2), true, false, true)
  413. JSON._putProp("stringify", r.newNativeFunc(r.builtinJSON_stringify, nil, "stringify", nil, 3), true, false, true)
  414. r.addToGlobal("JSON", JSON.val)
  415. }