js protocol: fix breaking json export issue

This commit is contained in:
Tarun Koyalwar 2024-03-15 18:04:08 +05:30
parent aaf3cf9cb3
commit 94817ca300

View File

@ -138,8 +138,7 @@ func executeWithPoolingProgram(p *goja.Program, args *ExecuteArgs, opts *Execute
return goja.Null() return goja.Null()
} }
for _, arg := range call.Arguments { for _, arg := range call.Arguments {
value := arg.Export() if out := stringify(arg, runtime); out != "" {
if out := stringify(value); out != "" {
buff.WriteString(out) buff.WriteString(out)
} }
} }
@ -158,8 +157,8 @@ func executeWithPoolingProgram(p *goja.Program, args *ExecuteArgs, opts *Execute
panic(runtime.ToValue("ExportAs expects 2 arguments")) panic(runtime.ToValue("ExportAs expects 2 arguments"))
} }
key := call.Argument(0).String() key := call.Argument(0).String()
value := call.Argument(1).Export() value := call.Argument(1)
opts.exports[key] = stringify(value) opts.exports[key] = stringify(value, runtime)
return goja.Null() return goja.Null()
}, },
}) })
@ -169,7 +168,7 @@ func executeWithPoolingProgram(p *goja.Program, args *ExecuteArgs, opts *Execute
} }
if val.Export() != nil { if val.Export() != nil {
// append last value to output // append last value to output
buff.WriteString(stringify(val.Export())) buff.WriteString(stringify(val, runtime))
} }
// and return it as result // and return it as result
return runtime.ToValue(buff.String()), nil return runtime.ToValue(buff.String()), nil
@ -201,13 +200,26 @@ func createNewRuntime() *goja.Runtime {
// stringify converts a given value to string // stringify converts a given value to string
// if its a struct it will be marshalled to json // if its a struct it will be marshalled to json
func stringify(value interface{}) string { func stringify(gojaValue goja.Value, runtime *goja.Runtime) string {
value := gojaValue.Export()
if value == nil { if value == nil {
return "" return ""
} }
kind := reflect.TypeOf(value).Kind() kind := reflect.TypeOf(value).Kind()
if kind == reflect.Struct || kind == reflect.Ptr && reflect.ValueOf(value).Elem().Kind() == reflect.Struct { if kind == reflect.Struct || kind == reflect.Ptr && reflect.ValueOf(value).Elem().Kind() == reflect.Struct {
// in this case we must use JSON.stringify to convert to string
// because json.Marshal() utilizes json tags when marshalling
// but goja has custom implementation of json.Marshal() which does not
// since we have been using `to_json` in all our examples we must stick to it
// marshal structs or struct pointers to json automatically // marshal structs or struct pointers to json automatically
jsonStringify, ok := goja.AssertFunction(runtime.Get("to_json"))
if ok {
result, err := jsonStringify(goja.Undefined(), gojaValue)
if err == nil {
return result.String()
}
}
// unlikely but if to_json throwed some error use native json.Marshal
val := value val := value
if kind == reflect.Ptr { if kind == reflect.Ptr {
val = reflect.ValueOf(value).Elem().Interface() val = reflect.ValueOf(value).Elem().Interface()