141 lines
3.0 KiB
Go
141 lines
3.0 KiB
Go
package goja
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestJSONMarshalObject(t *testing.T) {
|
|
vm := New()
|
|
o := vm.NewObject()
|
|
o.Set("test", 42)
|
|
o.Set("testfunc", vm.Get("Error"))
|
|
b, err := json.Marshal(o)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(b) != `{"test":42}` {
|
|
t.Fatalf("Unexpected value: %s", b)
|
|
}
|
|
}
|
|
|
|
func TestJSONMarshalGoDate(t *testing.T) {
|
|
vm := New()
|
|
o := vm.NewObject()
|
|
o.Set("test", time.Unix(86400, 0).UTC())
|
|
b, err := json.Marshal(o)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(b) != `{"test":"1970-01-02T00:00:00Z"}` {
|
|
t.Fatalf("Unexpected value: %s", b)
|
|
}
|
|
}
|
|
|
|
func TestJSONMarshalObjectCircular(t *testing.T) {
|
|
vm := New()
|
|
o := vm.NewObject()
|
|
o.Set("o", o)
|
|
_, err := json.Marshal(o)
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
if !strings.HasSuffix(err.Error(), "Converting circular structure to JSON") {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestJSONStringifyCircularWrappedGo(t *testing.T) {
|
|
type CircularType struct {
|
|
Self *CircularType
|
|
}
|
|
vm := New()
|
|
v := CircularType{}
|
|
v.Self = &v
|
|
vm.Set("v", &v)
|
|
_, err := vm.RunString("JSON.stringify(v)")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
if !strings.HasPrefix(err.Error(), "TypeError: Converting circular structure to JSON") {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestJSONParseReviver(t *testing.T) {
|
|
// example from
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
|
|
const SCRIPT = `
|
|
JSON.parse('{"p": 5}', function(key, value) {
|
|
return typeof value === 'number'
|
|
? value * 2 // return value * 2 for numbers
|
|
: value // return everything else unchanged
|
|
})["p"]
|
|
`
|
|
|
|
testScript(SCRIPT, intToValue(10), t)
|
|
}
|
|
|
|
func TestQuoteMalformedSurrogatePair(t *testing.T) {
|
|
testScript(`JSON.stringify("\uD800")`, asciiString(`"\ud800"`), t)
|
|
}
|
|
|
|
func TestEOFWrapping(t *testing.T) {
|
|
vm := New()
|
|
|
|
_, err := vm.RunString("JSON.parse('{')")
|
|
if err == nil {
|
|
t.Fatal("Expected error")
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), "Unexpected end of JSON input") {
|
|
t.Fatalf("Error doesn't contain human-friendly wrapper: %v", err)
|
|
}
|
|
}
|
|
|
|
type testMarshalJSONErrorStruct struct {
|
|
e error
|
|
}
|
|
|
|
func (s *testMarshalJSONErrorStruct) MarshalJSON() ([]byte, error) {
|
|
return nil, s.e
|
|
}
|
|
|
|
func TestMarshalJSONError(t *testing.T) {
|
|
vm := New()
|
|
v := testMarshalJSONErrorStruct{e: errors.New("test error")}
|
|
vm.Set("v", &v)
|
|
_, err := vm.RunString("JSON.stringify(v)")
|
|
if !errors.Is(err, v.e) {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func BenchmarkJSONStringify(b *testing.B) {
|
|
b.StopTimer()
|
|
vm := New()
|
|
var createObj func(level int) *Object
|
|
createObj = func(level int) *Object {
|
|
o := vm.NewObject()
|
|
o.Set("field1", "test")
|
|
o.Set("field2", 42)
|
|
if level > 0 {
|
|
level--
|
|
o.Set("obj1", createObj(level))
|
|
o.Set("obj2", createObj(level))
|
|
}
|
|
return o
|
|
}
|
|
|
|
o := createObj(3)
|
|
json := vm.Get("JSON").(*Object)
|
|
stringify, _ := AssertFunction(json.Get("stringify"))
|
|
b.StartTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
stringify(nil, o)
|
|
}
|
|
}
|