2024-02-17 12:55:08 +08:00
|
|
|
package gojs
|
|
|
|
|
|
|
|
import (
|
2024-06-26 12:04:45 +08:00
|
|
|
"apigo.cc/apigo/plugin"
|
2024-07-04 11:10:22 +08:00
|
|
|
"apigo.cc/apigo/quickjs-go"
|
2024-02-17 12:55:08 +08:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"github.com/ssgo/log"
|
|
|
|
"github.com/ssgo/u"
|
|
|
|
"reflect"
|
2024-05-27 13:12:15 +08:00
|
|
|
"regexp"
|
2024-02-17 12:55:08 +08:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
func MakeJsValue(ctx *plugin.Context, in interface{}, inArray bool) quickjs.Value {
|
|
|
|
return _makeJsValue(ctx, in, 0, "", "", inArray)
|
|
|
|
}
|
|
|
|
|
|
|
|
func MakeJsValueForPlugin(ctx *plugin.Context, in interface{}, pluginName string, inArray bool) quickjs.Value {
|
|
|
|
return _makeJsValue(ctx, in, 0, "", pluginName, inArray)
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeLowerCaseStartWord(str string) string {
|
|
|
|
if len(str) > 0 && str[0] >= 'A' && str[0] <= 'Z' {
|
|
|
|
return string(str[0]+32) + str[1:]
|
|
|
|
}
|
|
|
|
return str
|
|
|
|
}
|
|
|
|
|
|
|
|
func _makeJsValue(ctx *plugin.Context, in interface{}, n int, key string, pluginName string, inArray bool) quickjs.Value {
|
|
|
|
if n > 100 {
|
|
|
|
return quickjs.Value{}
|
|
|
|
}
|
|
|
|
jsCtx, jsCtxOk := ctx.GetInject("*quickjs.Context").(*quickjs.Context)
|
|
|
|
if !jsCtxOk {
|
|
|
|
return quickjs.Value{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err, isErr := in.(error); isErr {
|
|
|
|
return jsCtx.ThrowError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var v reflect.Value
|
|
|
|
//var ov reflect.To
|
|
|
|
if inV, ok := in.(reflect.Value); ok {
|
|
|
|
v = inV
|
|
|
|
} else {
|
|
|
|
//ov = reflect.ValueOf(in)
|
|
|
|
v = reflect.ValueOf(in)
|
|
|
|
}
|
|
|
|
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
|
2024-03-08 11:45:13 +08:00
|
|
|
if v.IsNil() {
|
|
|
|
return jsCtx.Null()
|
|
|
|
}
|
2024-02-17 12:55:08 +08:00
|
|
|
v = v.Elem()
|
|
|
|
}
|
2024-03-08 11:45:13 +08:00
|
|
|
if (v.Kind() == reflect.Slice || v.Kind() == reflect.Map || v.Kind() == reflect.Func) && v.IsNil() {
|
|
|
|
return jsCtx.Null()
|
|
|
|
}
|
2024-02-17 12:55:08 +08:00
|
|
|
switch v.Kind() {
|
|
|
|
case reflect.Bool:
|
|
|
|
return jsCtx.Bool(v.Bool())
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
|
|
|
|
return jsCtx.Int32(int32(v.Int()))
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
|
|
|
return jsCtx.Uint32(uint32(v.Uint()))
|
|
|
|
case reflect.Int64:
|
|
|
|
return jsCtx.Int64(v.Int())
|
|
|
|
case reflect.Uint64:
|
|
|
|
return jsCtx.Int64(int64(v.Uint()))
|
|
|
|
case reflect.String:
|
|
|
|
return jsCtx.String(v.String())
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
//return jsCtx.String(u.String(v.Float()))
|
|
|
|
return jsCtx.Float64(v.Float())
|
|
|
|
case reflect.Slice:
|
|
|
|
if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
|
|
|
|
originBuf := v.Bytes()
|
|
|
|
if len(originBuf) == 0 {
|
|
|
|
// 空的ArrayBuffer用空的Array代替
|
|
|
|
arr := jsCtx.Array()
|
|
|
|
arrValue := arr.ToValue()
|
|
|
|
if inArray {
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, arrValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arrValue
|
|
|
|
}
|
|
|
|
//if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
// *freeJsValues = append(*freeJsValues, bufValue)
|
|
|
|
//}
|
|
|
|
return jsCtx.ArrayBuffer(originBuf)
|
|
|
|
//arr := jsCtx.Array()
|
|
|
|
//for _, b := range v.Bytes() {
|
|
|
|
// o := jsCtx.Uint32(uint32(b))
|
|
|
|
// arr.Push(o)
|
|
|
|
//}
|
|
|
|
//if inArray {
|
|
|
|
// serverLogger.Error("==>2", n, key, "arr", "==")
|
|
|
|
// freeJsValues := ctx.GetData("_freeJsValues").(*[]quickjs.Value)
|
|
|
|
// *freeJsValues = append(*freeJsValues, arr.ToValue())
|
|
|
|
//}
|
|
|
|
//return arr.ToValue()
|
|
|
|
} else {
|
|
|
|
arr := jsCtx.Array()
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
o := _makeJsValue(ctx, v.Index(i), n+1, "", pluginName, true)
|
|
|
|
if o.IsObject() || o.IsArray() || o.IsMap() {
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arr.Push(o)
|
|
|
|
}
|
|
|
|
arrValue := arr.ToValue()
|
|
|
|
if inArray {
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, arrValue)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arrValue
|
|
|
|
}
|
|
|
|
case reflect.Struct:
|
|
|
|
o := jsCtx.Object()
|
|
|
|
var structInfo *u.StructInfo
|
|
|
|
if v.CanAddr() {
|
|
|
|
structInfo = u.FlatStruct(v.Addr())
|
|
|
|
} else {
|
|
|
|
structInfo = u.FlatStruct(v)
|
|
|
|
}
|
|
|
|
for k2, v2 := range structInfo.Values {
|
|
|
|
o.Set(makeLowerCaseStartWord(k2), _makeJsValue(ctx, v2, n+1, k2, pluginName, false))
|
|
|
|
}
|
|
|
|
for k2, v2 := range structInfo.MethodValues {
|
|
|
|
o.Set(makeLowerCaseStartWord(k2), _makeJsValue(ctx, v2, n+1, k2, pluginName, false))
|
|
|
|
}
|
|
|
|
return o
|
|
|
|
case reflect.Map:
|
|
|
|
o := jsCtx.Object()
|
|
|
|
for _, k2 := range v.MapKeys() {
|
|
|
|
k2s := u.String(u.FinalValue(k2).Interface())
|
|
|
|
if len(k2s) > 0 && k2s[0] != '_' {
|
2024-05-27 13:12:15 +08:00
|
|
|
v2 := _makeJsValue(ctx, v.MapIndex(k2), n+1, k2s, pluginName, false)
|
|
|
|
o.Set(k2s, v2)
|
2024-02-17 12:55:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return o
|
|
|
|
case reflect.Func:
|
|
|
|
t := v.Type()
|
|
|
|
return jsCtx.Function(func(js *quickjs.Context, this quickjs.Value, args []quickjs.Value) quickjs.Value {
|
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
ctx.GetInject("*log.Logger").(*log.Logger).Error(u.String(err), "func", key)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
needArgs := make([]reflect.Type, 0)
|
|
|
|
realArgs := make([]reflect.Value, t.NumIn())
|
|
|
|
needArgsIndex := map[int]int{}
|
|
|
|
for i := 0; i < t.NumIn(); i++ {
|
|
|
|
inTypeString := t.In(i).String()
|
|
|
|
if inTypeString == "*plugin.Context" {
|
|
|
|
realArgs[i] = reflect.ValueOf(ctx)
|
|
|
|
continue
|
|
|
|
//} else if inTypeString == "plugin.Config" {
|
|
|
|
// pluginConf := GetPluginConfig(pluginName)
|
|
|
|
// realArgs[i] = reflect.ValueOf(pluginConf)
|
|
|
|
// continue
|
2024-03-15 13:40:20 +08:00
|
|
|
//} else if injectObject := ctx.GetInject(inTypeString); injectObject != nil {
|
|
|
|
// realArgs[i] = reflect.ValueOf(injectObject)
|
|
|
|
// continue
|
2024-02-17 12:55:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if !realArgs[i].IsValid() {
|
|
|
|
needArgs = append(needArgs, t.In(i))
|
|
|
|
needArgsIndex[len(needArgsIndex)] = i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//if len(args) < len(needArgs) {
|
|
|
|
// return js.ThrowError(errors.New(fmt.Sprintf("call %s no enough args, need %d, given %d", key, len(needArgs), len(args))))
|
|
|
|
//}
|
|
|
|
for i, needArgType := range needArgs {
|
|
|
|
var argValue reflect.Value
|
|
|
|
isLastVariadicArg := false
|
|
|
|
if v.Type().IsVariadic() && needArgsIndex[i] == len(realArgs)-1 {
|
|
|
|
// 可变参数函数的最后一个使用成员类型
|
|
|
|
isLastVariadicArg = true
|
|
|
|
argValue = reflect.New(needArgType.Elem())
|
|
|
|
} else {
|
|
|
|
argValue = reflect.New(needArgType)
|
|
|
|
}
|
|
|
|
if i > len(args)-1 {
|
|
|
|
if !isLastVariadicArg && needArgType.Kind() != reflect.Interface && needArgType.Kind() != reflect.Ptr {
|
|
|
|
return js.ThrowError(errors.New(fmt.Sprintf("call %s no enough args, need %d, given %d", key, len(needArgs), len(args))))
|
|
|
|
}
|
|
|
|
realArgs[needArgsIndex[i]] = reflect.ValueOf(argValue.Interface()).Elem()
|
|
|
|
} else if needArgType.Kind() == reflect.Func {
|
|
|
|
jsFunc := args[i]
|
|
|
|
funcType := needArgType
|
2024-05-27 13:12:15 +08:00
|
|
|
funcCode := jsFunc.String()
|
|
|
|
funcId := ""
|
|
|
|
if !jsFuncNameMatcher.MatchString(funcCode) {
|
|
|
|
anonymousFuncIndex := u.Uint64(ctx.GetData("anonymousFuncIndex")) + 1
|
|
|
|
ctx.SetData("anonymousFuncIndex", anonymousFuncIndex)
|
|
|
|
funcId = "_func_" + u.String(anonymousFuncIndex) + "_" + u.ShortUniqueId()
|
|
|
|
jsCtx.Eval("var " + funcId + " = " + funcCode)
|
|
|
|
}
|
2024-02-17 12:55:08 +08:00
|
|
|
argValue = reflect.MakeFunc(funcType, func(goArgs []reflect.Value) []reflect.Value {
|
2024-05-27 13:12:15 +08:00
|
|
|
if !jsFunc.IsFunction() && funcId != "" {
|
|
|
|
jsFunc2 := jsCtx.Globals().Get(funcId)
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, jsFunc2)
|
|
|
|
}
|
|
|
|
if jsFunc2.IsFunction() {
|
|
|
|
jsFunc = jsFunc2
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-17 12:55:08 +08:00
|
|
|
ins := make([]quickjs.Value, 0)
|
2024-05-27 13:12:15 +08:00
|
|
|
j := 0
|
|
|
|
for i := 0; i < len(goArgs); i++ {
|
|
|
|
if j >= funcType.NumIn() {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
var jV interface{}
|
|
|
|
if funcType.IsVariadic() && j == funcType.NumIn()-1 && funcType.In(j).Kind() == reflect.Slice {
|
|
|
|
jV = reflect.New(funcType.In(j).Elem()).Interface()
|
|
|
|
} else {
|
|
|
|
jV = reflect.New(funcType.In(j)).Interface()
|
|
|
|
j++
|
|
|
|
}
|
|
|
|
u.Convert(goArgs[i].Interface(), jV)
|
|
|
|
ins = append(ins, MakeJsValue(ctx, reflect.ValueOf(jV).Elem(), false))
|
2024-02-17 12:55:08 +08:00
|
|
|
}
|
2024-05-27 13:12:15 +08:00
|
|
|
//for _, goArg := range goArgs {
|
|
|
|
// ins = append(ins, MakeJsValue(ctx, goArg.Interface(), false))
|
|
|
|
//}
|
|
|
|
//for j := 0; j < funcType.NumIn(); j++ {
|
|
|
|
// if j < len(goArgs) {
|
|
|
|
// if goArgs[j].Type() == funcType.In(j) {
|
|
|
|
// fmt.Println(111, goArgs[j].Type(), funcType.In(j))
|
|
|
|
// inArg := reflect.New(funcType.In(j))
|
|
|
|
// inArgValue := inArg.Interface()
|
|
|
|
// u.Convert(goArgs[j].Interface(), inArgValue)
|
|
|
|
// ins = append(ins, MakeJsValue(ctx, reflect.ValueOf(inArgValue).Elem(), false))
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// ins = append(ins, MakeJsValue(ctx, reflect.New(funcType.In(j)).Elem(), false))
|
|
|
|
// }
|
|
|
|
//}
|
2024-02-17 12:55:08 +08:00
|
|
|
outs := make([]reflect.Value, 0)
|
|
|
|
jsResult := jsCtx.Invoke(jsFunc, jsCtx.Null(), ins...)
|
2024-05-27 13:12:15 +08:00
|
|
|
if !jsResult.IsUndefined() {
|
|
|
|
if funcType.NumOut() == 1 {
|
|
|
|
out0P := reflect.New(funcType.Out(0)).Interface()
|
|
|
|
u.Convert(MakeFromJsValue(jsResult, ctx), out0P)
|
|
|
|
outs = append(outs, reflect.ValueOf(out0P).Elem())
|
|
|
|
} else if funcType.NumOut() > 1 {
|
|
|
|
if jsResult.IsArray() && int(jsResult.Len()) <= funcType.NumOut() {
|
|
|
|
for j := 0; j < funcType.NumOut(); j++ {
|
|
|
|
if j < int(jsResult.Len()) {
|
|
|
|
out0P := reflect.New(funcType.Out(j)).Interface()
|
|
|
|
u.Convert(MakeFromJsValue(jsResult.GetIdx(int64(j)), ctx), out0P)
|
|
|
|
outs = append(outs, reflect.ValueOf(out0P).Elem())
|
|
|
|
} else {
|
|
|
|
outs = append(outs, reflect.New(funcType.Out(j)).Elem())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
out0P := reflect.New(funcType.Out(0)).Interface()
|
|
|
|
u.Convert(MakeFromJsValue(jsResult, ctx), out0P)
|
|
|
|
outs = append(outs, reflect.ValueOf(out0P).Elem())
|
|
|
|
for j := 1; j < funcType.NumOut(); j++ {
|
|
|
|
outs = append(outs, reflect.New(funcType.Out(j)).Elem())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for j := 0; j < funcType.NumOut(); j++ {
|
|
|
|
outs = append(outs, reflect.New(funcType.Out(j)).Elem())
|
|
|
|
}
|
2024-02-17 12:55:08 +08:00
|
|
|
}
|
|
|
|
return outs
|
2024-05-27 13:12:15 +08:00
|
|
|
|
|
|
|
//ins := make([]reflect.Value, 0)
|
|
|
|
//j := 0
|
|
|
|
//for i := 0; i < len(goArgs); i++ {
|
|
|
|
// if j >= fromType.NumIn() {
|
|
|
|
// break
|
|
|
|
// }
|
|
|
|
// var jV interface{}
|
|
|
|
// if fromType.IsVariadic() && j == fromType.NumIn()-1 && fromType.In(j).Kind() == reflect.Slice {
|
|
|
|
// jV = reflect.New(fromType.In(j).Elem()).Interface()
|
|
|
|
// } else {
|
|
|
|
// jV = reflect.New(fromType.In(j)).Interface()
|
|
|
|
// j++
|
|
|
|
// }
|
|
|
|
// convert(goArgs[i].Interface(), jV)
|
|
|
|
// ins = append(ins, reflect.ValueOf(jV).Elem())
|
|
|
|
//}
|
|
|
|
//out := fromValue.Call(ins)
|
|
|
|
//outs := make([]reflect.Value, 0)
|
|
|
|
//j = 0
|
|
|
|
//for i := 0; i < toType.NumOut(); i++ {
|
|
|
|
// iV := reflect.New(toType.Out(i)).Interface()
|
|
|
|
// var jV interface{}
|
|
|
|
// if toType.NumOut() > len(out) && j == len(out)-1 && out[j].Kind() == reflect.Slice {
|
|
|
|
// if out[j].Len() > i-j {
|
|
|
|
// jV = out[j].Index(i - j).Interface()
|
|
|
|
// convert(jV, iV)
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// jV = out[j].Interface()
|
|
|
|
// convert(jV, iV)
|
|
|
|
// j++
|
|
|
|
// }
|
|
|
|
// outs = append(outs, reflect.ValueOf(iV).Elem())
|
|
|
|
//}
|
|
|
|
//return outs
|
|
|
|
|
2024-02-17 12:55:08 +08:00
|
|
|
})
|
|
|
|
realArgs[needArgsIndex[i]] = argValue
|
|
|
|
} else {
|
|
|
|
//fmt.Println(222, len(args), len(needArgs), reflect.TypeOf(MakeFromJsValue(args[i])).String(), reflect.TypeOf(argValue).String(), MakeFromJsValue(args[i]), argValue)
|
|
|
|
argValueP := argValue.Interface()
|
2024-05-27 13:12:15 +08:00
|
|
|
ff1 := MakeFromJsValue(args[i], ctx)
|
2024-02-17 12:55:08 +08:00
|
|
|
u.Convert(ff1, argValueP)
|
|
|
|
argValue = reflect.ValueOf(argValueP).Elem()
|
|
|
|
realArgs[needArgsIndex[i]] = argValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 处理可变参数
|
|
|
|
if len(args) > len(needArgs) {
|
|
|
|
lastArgType := needArgs[len(needArgs)-1]
|
|
|
|
if lastArgType.Kind() == reflect.Slice && lastArgType.Elem().Kind() != reflect.Uint8 {
|
|
|
|
//lastRealArgIndex := needArgsIndex[len(needArgs)-1]
|
|
|
|
//fmt.Println(222221, realArgs[lastRealArgIndex].Type().String())
|
|
|
|
for i := len(needArgs); i < len(args); i++ {
|
|
|
|
argValue := reflect.New(lastArgType.Elem()).Interface()
|
|
|
|
//fmt.Println(22222, len(args), len(needArgs), reflect.TypeOf(MakeFromJsValue(args[i])).String(), reflect.TypeOf(argValue).String(), MakeFromJsValue(args[i]), argValue)
|
2024-05-27 13:12:15 +08:00
|
|
|
u.Convert(MakeFromJsValue(args[i], ctx), argValue)
|
2024-02-17 12:55:08 +08:00
|
|
|
realArgs = append(realArgs, reflect.ValueOf(argValue).Elem())
|
|
|
|
//realArgs[lastRealArgIndex] = reflect.Append(realArgs[lastRealArgIndex], reflect.ValueOf(argValue).Elem())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
outValues := v.Call(realArgs)
|
|
|
|
outs := make([]reflect.Value, 0)
|
|
|
|
for _, outValue := range outValues {
|
|
|
|
if outValue.Type().String() == "error" {
|
|
|
|
if !outValue.IsNil() {
|
|
|
|
// 抛出异常
|
|
|
|
return _makeJsValue(ctx, outValue.Interface(), n+1, "", pluginName, false)
|
|
|
|
}
|
|
|
|
// 忽略error参数
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
outs = append(outs, outValue)
|
|
|
|
}
|
|
|
|
if len(outs) == 1 {
|
|
|
|
//fmt.Println("**out, ", u.JsonP(outs[0].Interface()), "**")
|
|
|
|
out := _makeJsValue(ctx, outs[0].Interface(), n+1, "", pluginName, false)
|
|
|
|
return out
|
|
|
|
} else if len(outs) > 1 {
|
|
|
|
arr := jsCtx.Array()
|
|
|
|
for _, outValue := range outs {
|
|
|
|
//r.Set(int64(i), _makeJsValue(ctx, outValue.Interface(), n+1, "", pluginName, inReturn))
|
|
|
|
o := _makeJsValue(ctx, outValue.Interface(), n+1, "", pluginName, true)
|
|
|
|
if o.IsObject() || o.IsArray() || o.IsMap() {
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arr.Push(o)
|
|
|
|
}
|
|
|
|
return arr.ToValue()
|
|
|
|
} else {
|
|
|
|
return jsCtx.Null()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
case reflect.Invalid:
|
|
|
|
return jsCtx.Null()
|
|
|
|
default:
|
|
|
|
return jsCtx.String(u.String(in))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-27 13:12:15 +08:00
|
|
|
func MakeFromJsValue(in quickjs.Value, ctx *plugin.Context) interface{} {
|
|
|
|
return _makeFromJsValue(in, in.Context().Null(), "", 0, ctx)
|
2024-02-17 12:55:08 +08:00
|
|
|
}
|
|
|
|
|
2024-05-27 13:12:15 +08:00
|
|
|
var jsFuncNameMatcher = regexp.MustCompile(`function\s+(\w+)\s*\(`)
|
|
|
|
|
|
|
|
func _makeFromJsValue(in quickjs.Value, parent quickjs.Value, key string, n int, ctx *plugin.Context) interface{} {
|
2024-02-17 12:55:08 +08:00
|
|
|
if n > 100 {
|
|
|
|
return quickjs.Value{}
|
|
|
|
}
|
|
|
|
if in.IsBool() {
|
|
|
|
return in.Bool()
|
|
|
|
} else if in.IsBigInt() {
|
|
|
|
return in.Int64()
|
|
|
|
} else if in.IsBigFloat() || in.IsBigDecimal() {
|
|
|
|
return in.Float64()
|
|
|
|
} else if in.IsNumber() {
|
|
|
|
if strings.ContainsRune(in.String(), '.') {
|
|
|
|
return in.Float64()
|
|
|
|
} else {
|
|
|
|
return in.Int64()
|
|
|
|
}
|
|
|
|
} else if in.IsString() {
|
|
|
|
return in.String()
|
|
|
|
} else if in.IsByteArray() {
|
|
|
|
buf, err := in.ToByteArray(uint(in.ByteLen()))
|
|
|
|
if err != nil {
|
|
|
|
return []byte{}
|
|
|
|
}
|
|
|
|
return buf
|
|
|
|
} else if in.IsArray() {
|
|
|
|
a := make([]interface{}, 0)
|
|
|
|
//isBytes := true
|
|
|
|
//isChars := true
|
|
|
|
arr := in.ToArray()
|
|
|
|
for i := int64(0); i < arr.Len(); i++ {
|
|
|
|
if v, err := arr.Get(i); err == nil {
|
2024-05-27 13:12:15 +08:00
|
|
|
value := _makeFromJsValue(v, in.Context().Null(), "", n+1, ctx)
|
2024-02-17 12:55:08 +08:00
|
|
|
a = append(a, value)
|
|
|
|
//value.Free()
|
|
|
|
v.Free()
|
|
|
|
//_freeJsValues = append(_freeJsValues, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
//v := in.GetIdx(int64(i))
|
|
|
|
//value := _makeFromJsValue(v, n+1)
|
|
|
|
////if isChars {
|
|
|
|
//// // 判断是否 Uint16Array 或 Uint8Array
|
|
|
|
//// if !v.IsNumber() {
|
|
|
|
//// isBytes = false
|
|
|
|
//// isChars = false
|
|
|
|
//// }
|
|
|
|
////}
|
|
|
|
////if isBytes {
|
|
|
|
//// // 判断是否 Uint8Array
|
|
|
|
//// if v.Int64() > 255 {
|
|
|
|
//// isBytes = false
|
|
|
|
//// }
|
|
|
|
////}
|
|
|
|
//a = append(a, value)
|
|
|
|
//v.Free()
|
|
|
|
}
|
|
|
|
//arr.Free()
|
|
|
|
//_freeJsValues = append(_freeJsValues, in)
|
|
|
|
|
|
|
|
//if isBytes {
|
|
|
|
// buf := make([]byte, len(a))
|
|
|
|
// for i, arrV := range a {
|
|
|
|
// buf[i] = byte(u.Uint(arrV))
|
|
|
|
// }
|
|
|
|
// return buf
|
|
|
|
//}
|
|
|
|
//if isChars {
|
|
|
|
// buf := make([]rune, len(a))
|
|
|
|
// for i, arrV := range a {
|
|
|
|
// buf[i] = rune(u.Uint(arrV))
|
|
|
|
// }
|
|
|
|
// return buf
|
|
|
|
//}
|
|
|
|
return a
|
|
|
|
} else if in.IsFunction() {
|
2024-05-27 13:12:15 +08:00
|
|
|
jsCtx := ctx.GetInject("*quickjs.Context").(*quickjs.Context)
|
|
|
|
funcCode := in.String()
|
|
|
|
funcId := ""
|
|
|
|
if !jsFuncNameMatcher.MatchString(funcCode) {
|
2024-07-10 10:17:07 +08:00
|
|
|
funcId = u.String(ctx.GetData("_func_" + funcCode))
|
|
|
|
if funcId == "" {
|
|
|
|
anonymousFuncIndex := u.Uint64(ctx.GetData("anonymousFuncIndex")) + 1
|
|
|
|
ctx.SetData("anonymousFuncIndex", anonymousFuncIndex)
|
|
|
|
funcId = "_func_" + u.String(anonymousFuncIndex) + "_" + u.ShortUniqueId()
|
|
|
|
ctx.SetData("_func_"+funcCode, funcId)
|
|
|
|
jsCtx.Eval("var " + funcId + " = " + funcCode)
|
|
|
|
}
|
2024-05-27 13:12:15 +08:00
|
|
|
}
|
|
|
|
return func(args ...interface{}) interface{} {
|
2024-07-10 10:17:07 +08:00
|
|
|
// 匿名函数从全局变量获得(命名函数可直接获得)
|
2024-05-27 13:12:15 +08:00
|
|
|
if !in.IsFunction() && funcId != "" {
|
|
|
|
in2 := jsCtx.Globals().Get(funcId)
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, in2)
|
|
|
|
}
|
|
|
|
if in2.IsFunction() {
|
|
|
|
in = in2
|
|
|
|
}
|
|
|
|
}
|
2024-07-10 10:17:07 +08:00
|
|
|
|
2024-05-27 13:12:15 +08:00
|
|
|
jsIn := make([]quickjs.Value, len(args))
|
|
|
|
for i, arg := range args {
|
|
|
|
jsIn[i] = MakeJsValue(ctx, arg, false)
|
|
|
|
if freeJsValues, ok := ctx.GetData("_freeJsValues").(*[]quickjs.Value); ok {
|
|
|
|
*freeJsValues = append(*freeJsValues, jsIn[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var jsOut quickjs.Value
|
|
|
|
if key != "" && !parent.IsNull() {
|
|
|
|
//jsOut = parent.Call(key, jsIn...)
|
|
|
|
//jsOut = jsCtx.Invoke(in, parent, jsIn...)
|
|
|
|
jsOut = jsCtx.Invoke(in, jsCtx.Null(), jsIn...)
|
|
|
|
} else {
|
|
|
|
jsOut = jsCtx.Invoke(in, jsCtx.Null(), jsIn...)
|
|
|
|
}
|
2024-07-10 10:17:07 +08:00
|
|
|
out := MakeFromJsValue(jsOut, ctx)
|
|
|
|
jsOut.Free()
|
|
|
|
return out
|
2024-05-27 13:12:15 +08:00
|
|
|
}
|
2024-02-17 12:55:08 +08:00
|
|
|
} else if in.IsObject() {
|
|
|
|
o := map[string]interface{}{}
|
|
|
|
keys, _ := in.PropertyNames()
|
|
|
|
isBytes := true
|
|
|
|
isChars := true
|
|
|
|
isArray := true
|
|
|
|
arr := make([]interface{}, 0)
|
|
|
|
for i, k := range keys {
|
|
|
|
if k == "prototype" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
v := in.Get(k)
|
2024-05-27 13:12:15 +08:00
|
|
|
value := _makeFromJsValue(v, in, k, n+1, ctx)
|
2024-02-17 12:55:08 +08:00
|
|
|
// 判断是否数组类对象
|
|
|
|
if (i == 0 && k != "0") || (i > 0 && u.Int(k) != i) {
|
|
|
|
isBytes = false
|
|
|
|
isChars = false
|
|
|
|
isArray = false
|
|
|
|
}
|
|
|
|
if isArray {
|
|
|
|
if isChars {
|
|
|
|
// 判断是否 Uint16Array 或 Uint8Array
|
|
|
|
if !v.IsNumber() {
|
|
|
|
isBytes = false
|
|
|
|
isChars = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if isBytes {
|
|
|
|
// 判断是否 Uint8Array
|
|
|
|
if v.Int64() > 255 {
|
|
|
|
isBytes = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arr = append(arr, value)
|
|
|
|
}
|
|
|
|
o[k] = value
|
|
|
|
v.Free()
|
|
|
|
}
|
|
|
|
|
|
|
|
if isBytes {
|
|
|
|
buf := make([]byte, len(arr))
|
|
|
|
for i, arrV := range arr {
|
|
|
|
buf[i] = byte(u.Uint(arrV))
|
|
|
|
}
|
|
|
|
return buf
|
|
|
|
}
|
|
|
|
if isChars {
|
|
|
|
buf := make([]rune, len(arr))
|
|
|
|
for i, arrV := range arr {
|
|
|
|
buf[i] = rune(u.Uint(arrV))
|
|
|
|
}
|
|
|
|
return buf
|
|
|
|
}
|
|
|
|
if isArray {
|
|
|
|
return arr
|
|
|
|
}
|
|
|
|
return o
|
|
|
|
} else if in.IsNull() || in.IsUndefined() || in.IsUninitialized() {
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return in.String()
|
|
|
|
}
|
|
|
|
}
|