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