builtin_json_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 TestJSONParseReviver(t *testing.T) {
  47. // example from
  48. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
  49. const SCRIPT = `
  50. JSON.parse('{"p": 5}', function(key, value) {
  51. return typeof value === 'number'
  52. ? value * 2 // return value * 2 for numbers
  53. : value // return everything else unchanged
  54. })["p"]
  55. `
  56. testScript(SCRIPT, intToValue(10), t)
  57. }
  58. func TestQuoteMalformedSurrogatePair(t *testing.T) {
  59. testScript(`JSON.stringify("\uD800")`, asciiString(`"\ud800"`), t)
  60. }
  61. func TestEOFWrapping(t *testing.T) {
  62. vm := New()
  63. _, err := vm.RunString("JSON.parse('{')")
  64. if err == nil {
  65. t.Fatal("Expected error")
  66. }
  67. if !strings.Contains(err.Error(), "Unexpected end of JSON input") {
  68. t.Fatalf("Error doesn't contain human-friendly wrapper: %v", err)
  69. }
  70. }
  71. type testMarshalJSONErrorStruct struct {
  72. e error
  73. }
  74. func (s *testMarshalJSONErrorStruct) MarshalJSON() ([]byte, error) {
  75. return nil, s.e
  76. }
  77. func TestMarshalJSONError(t *testing.T) {
  78. vm := New()
  79. v := testMarshalJSONErrorStruct{e: errors.New("test error")}
  80. vm.Set("v", &v)
  81. _, err := vm.RunString("JSON.stringify(v)")
  82. if !errors.Is(err, v.e) {
  83. t.Fatalf("Unexpected error: %v", err)
  84. }
  85. }
  86. func BenchmarkJSONStringify(b *testing.B) {
  87. b.StopTimer()
  88. vm := New()
  89. var createObj func(level int) *Object
  90. createObj = func(level int) *Object {
  91. o := vm.NewObject()
  92. o.Set("field1", "test")
  93. o.Set("field2", 42)
  94. if level > 0 {
  95. level--
  96. o.Set("obj1", createObj(level))
  97. o.Set("obj2", createObj(level))
  98. }
  99. return o
  100. }
  101. o := createObj(3)
  102. json := vm.Get("JSON").(*Object)
  103. stringify, _ := AssertFunction(json.Get("stringify"))
  104. b.StartTimer()
  105. for i := 0; i < b.N; i++ {
  106. stringify(nil, o)
  107. }
  108. }