builtin_json_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package goja
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "strings"
  6. "testing"
  7. "time"
  8. )
  9. func TestJSONMarshalObject(t *testing.T) {
  10. vm := New()
  11. o := vm.NewObject()
  12. o.Set("test", 42)
  13. o.Set("testfunc", vm.Get("Error"))
  14. b, err := json.Marshal(o)
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. if string(b) != `{"test":42}` {
  19. t.Fatalf("Unexpected value: %s", b)
  20. }
  21. }
  22. func TestJSONMarshalGoDate(t *testing.T) {
  23. vm := New()
  24. o := vm.NewObject()
  25. o.Set("test", time.Unix(86400, 0).UTC())
  26. b, err := json.Marshal(o)
  27. if err != nil {
  28. t.Fatal(err)
  29. }
  30. if string(b) != `{"test":"1970-01-02T00:00:00Z"}` {
  31. t.Fatalf("Unexpected value: %s", b)
  32. }
  33. }
  34. func TestJSONMarshalObjectCircular(t *testing.T) {
  35. vm := New()
  36. o := vm.NewObject()
  37. o.Set("o", o)
  38. _, err := json.Marshal(o)
  39. if err == nil {
  40. t.Fatal("Expected error")
  41. }
  42. if !strings.HasSuffix(err.Error(), "Converting circular structure to JSON") {
  43. t.Fatalf("Unexpected error: %v", err)
  44. }
  45. }
  46. func TestJSONStringifyCircularWrappedGo(t *testing.T) {
  47. type CircularType struct {
  48. Self *CircularType
  49. }
  50. vm := New()
  51. v := CircularType{}
  52. v.Self = &v
  53. vm.Set("v", &v)
  54. _, err := vm.RunString("JSON.stringify(v)")
  55. if err == nil {
  56. t.Fatal("Expected error")
  57. }
  58. if !strings.HasPrefix(err.Error(), "TypeError: Converting circular structure to JSON") {
  59. t.Fatalf("Unexpected error: %v", err)
  60. }
  61. }
  62. func TestJSONParseReviver(t *testing.T) {
  63. // example from
  64. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
  65. const SCRIPT = `
  66. JSON.parse('{"p": 5}', function(key, value) {
  67. return typeof value === 'number'
  68. ? value * 2 // return value * 2 for numbers
  69. : value // return everything else unchanged
  70. })["p"]
  71. `
  72. testScript(SCRIPT, intToValue(10), t)
  73. }
  74. func TestQuoteMalformedSurrogatePair(t *testing.T) {
  75. testScript(`JSON.stringify("\uD800")`, asciiString(`"\ud800"`), t)
  76. }
  77. func TestEOFWrapping(t *testing.T) {
  78. vm := New()
  79. _, err := vm.RunString("JSON.parse('{')")
  80. if err == nil {
  81. t.Fatal("Expected error")
  82. }
  83. if !strings.Contains(err.Error(), "Unexpected end of JSON input") {
  84. t.Fatalf("Error doesn't contain human-friendly wrapper: %v", err)
  85. }
  86. }
  87. type testMarshalJSONErrorStruct struct {
  88. e error
  89. }
  90. func (s *testMarshalJSONErrorStruct) MarshalJSON() ([]byte, error) {
  91. return nil, s.e
  92. }
  93. func TestMarshalJSONError(t *testing.T) {
  94. vm := New()
  95. v := testMarshalJSONErrorStruct{e: errors.New("test error")}
  96. vm.Set("v", &v)
  97. _, err := vm.RunString("JSON.stringify(v)")
  98. if !errors.Is(err, v.e) {
  99. t.Fatalf("Unexpected error: %v", err)
  100. }
  101. }
  102. func BenchmarkJSONStringify(b *testing.B) {
  103. b.StopTimer()
  104. vm := New()
  105. var createObj func(level int) *Object
  106. createObj = func(level int) *Object {
  107. o := vm.NewObject()
  108. o.Set("field1", "test")
  109. o.Set("field2", 42)
  110. if level > 0 {
  111. level--
  112. o.Set("obj1", createObj(level))
  113. o.Set("obj2", createObj(level))
  114. }
  115. return o
  116. }
  117. o := createObj(3)
  118. json := vm.Get("JSON").(*Object)
  119. stringify, _ := AssertFunction(json.Get("stringify"))
  120. b.StartTimer()
  121. for i := 0; i < b.N; i++ {
  122. stringify(nil, o)
  123. }
  124. }