mirror of
https://gitee.com/energye/energy.git
synced 2024-11-30 10:47:57 +08:00
498 lines
17 KiB
Go
498 lines
17 KiB
Go
//----------------------------------------
|
||
//
|
||
// Copyright © yanghy. All Rights Reserved.
|
||
//
|
||
// Licensed under Apache License Version 2.0, January 2004
|
||
//
|
||
// https://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
//----------------------------------------
|
||
|
||
// CEF IPC 事件实现
|
||
package cef
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/binary"
|
||
"github.com/energye/energy/common"
|
||
"github.com/energye/energy/common/imports"
|
||
. "github.com/energye/energy/consts"
|
||
"github.com/energye/energy/ipc"
|
||
"github.com/energye/energy/logger"
|
||
"github.com/energye/golcl/lcl/api"
|
||
"github.com/energye/golcl/lcl/api/dllimports"
|
||
"net"
|
||
"reflect"
|
||
"strings"
|
||
"unsafe"
|
||
)
|
||
|
||
const (
|
||
IPC_FN_TYPE_IPCJSEmitGo = 1 // JS fires the Go registerChromiumEvent
|
||
IPC_FN_TYPE_IPCGoEmitJSRet = 2 // Go fires the JS registerChromiumEvent
|
||
)
|
||
|
||
var (
|
||
setCefIPCCallbackFunc dllimports.ProcAddr
|
||
)
|
||
|
||
type rGoResult struct {
|
||
value uintptr //Pointer
|
||
valueType uintptr //PInteger
|
||
valueLength uintptr //PInteger
|
||
bindType uintptr //PInteger
|
||
exception uintptr //PInteger
|
||
}
|
||
|
||
func (m *rGoResult) set(value, valueType, valueLength, bindType, exception uintptr) {
|
||
m.value = value
|
||
m.valueType = valueType
|
||
m.valueLength = valueLength
|
||
m.bindType = bindType
|
||
m.exception = exception
|
||
}
|
||
|
||
type rIPCEventParam struct {
|
||
BrowserId int32
|
||
IPCId int32
|
||
FullName uintptr //string
|
||
FrameId uintptr //string
|
||
ParamType int32 //js中ipc.emit参数类型: 1:没有入参和回调函数 2:有入参 没有回调函数 3:没有入参 有回调函数 4:有入参 有回调函数
|
||
ValueTypeArrLen int32 //参数个数
|
||
ValueTypeArr uintptr //ValueTypeArr: array of byte;
|
||
}
|
||
|
||
func cefIPCInit() {
|
||
setCefIPCCallbackFunc = imports.Proc(internale_SetCEFIPCCallbackFunc)
|
||
setCefIPCCallbackFunc.Call(cefIPCCallbackFuncEvent)
|
||
}
|
||
|
||
func cefIPCEventProc(fnType uintptr, args uintptr, argsLen int) uintptr {
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
logger.Error("IPCEventProc Error:", err)
|
||
}
|
||
}()
|
||
getVal := func(i int) uintptr {
|
||
return common.GetParamOf(i, args)
|
||
}
|
||
getPtr := func(i int) unsafe.Pointer {
|
||
return unsafe.Pointer(getVal(i))
|
||
}
|
||
if fnType == IPC_FN_TYPE_IPCJSEmitGo {
|
||
eventParam := (*rIPCEventParam)(getPtr(0))
|
||
result := (*rGoResult)(getPtr(1))
|
||
if eventParam == nil || result == nil {
|
||
return 0
|
||
}
|
||
ipcJSEmitGo(eventParam, result, args)
|
||
} else if fnType == IPC_FN_TYPE_IPCGoEmitJSRet {
|
||
ipcId := *(*int32)(getPtr(0))
|
||
tmType := *(*int32)(getPtr(1))
|
||
result := (*rGoResult)(getPtr(2))
|
||
ipcGoEmitJS(ipcId, TriggerMode(tmType), result, args)
|
||
result.set(0, 0, 0, 0, 0)
|
||
result = nil
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// ipc - go emit js on event
|
||
func ipcGoEmitJS(ipcId int32, triggerMode TriggerMode, result *rGoResult, args uintptr) {
|
||
inArgument := ipc.NewArgumentList()
|
||
inArgument.SetBool(1, true)
|
||
if CEF_V8_EXCEPTION(result.exception) == CVE_ERROR_OK {
|
||
switch V8_JS_VALUE_TYPE(result.valueType) {
|
||
case V8_VALUE_STRING:
|
||
inArgument.SetString(0, api.GoStr(result.value))
|
||
case V8_VALUE_INT:
|
||
inArgument.SetInt32(0, int32(result.value))
|
||
case V8_VALUE_DOUBLE:
|
||
inArgument.SetFloat64(0, *(*float64)(common.GetParamPtr(result.value, 0)))
|
||
case V8_VALUE_BOOLEAN:
|
||
inArgument.SetBool(0, *(*bool)(common.GetParamPtr(result.value, 0)))
|
||
default:
|
||
inArgument.SetBool(1, false)
|
||
inArgument.SetString(0, "不支持的数据类型")
|
||
}
|
||
} else {
|
||
inArgument.SetBool(1, false)
|
||
inArgument.SetString(0, api.GoStr(result.value))
|
||
}
|
||
if triggerMode == Tm_Callback { //回调函数
|
||
if callback, ok := executeJS.emitCallback.EmitCollection.Load(ipcId); ok {
|
||
executeJS.emitCallback.EmitCollection.Delete(ipcId)
|
||
ctx := ipc.NewIPCContext("", 0, 0, 0, nil, nil, &ipc.IPCContextResult{}, inArgument)
|
||
callback.(ipc.IPCCallback)(ctx)
|
||
ctx.Free()
|
||
}
|
||
} else if triggerMode == Tm_Sync { //同步调用
|
||
if chn, ok := executeJS.emitSync.EmitCollection.Load(ipcId); ok {
|
||
ctx := ipc.NewIPCContext("", 0, 0, 0, nil, nil, &ipc.IPCContextResult{}, inArgument)
|
||
var c = chn.(chan ipc.IIPCContext)
|
||
c <- ctx
|
||
close(c)
|
||
executeJS.emitSync.EmitCollection.Delete(ctx.EventId())
|
||
}
|
||
}
|
||
}
|
||
|
||
// ipc - js emit go on event
|
||
func ipcJSEmitGo(eventParam *rIPCEventParam, result *rGoResult, args uintptr) {
|
||
getVal := func(i int) uintptr {
|
||
return common.GetParamOf(i, args)
|
||
}
|
||
getPtr := func(i int) unsafe.Pointer {
|
||
return unsafe.Pointer(getVal(i))
|
||
}
|
||
var (
|
||
inArgument = ipc.NewArgumentList()
|
||
fullName = api.GoStr(eventParam.FullName)
|
||
valueTypeLen = eventParam.ValueTypeArrLen //入参类型数组
|
||
accIdx = 2 //占用的下标
|
||
)
|
||
if valueTypeLen > 0 {
|
||
//取入参
|
||
for i := 0; i < int(valueTypeLen); i++ {
|
||
valueType := V8_JS_VALUE_TYPE(*(*byte)(common.GetParamPtr(eventParam.ValueTypeArr, i)))
|
||
switch valueType {
|
||
case V8_VALUE_STRING:
|
||
inArgument.SetString(i, api.GoStr(getVal(i+accIdx)))
|
||
case V8_VALUE_INT:
|
||
inArgument.SetInt32(i, int32(getVal(i+accIdx)))
|
||
case V8_VALUE_DOUBLE:
|
||
inArgument.SetFloat64(i, *(*float64)(getPtr(i + accIdx)))
|
||
case V8_VALUE_BOOLEAN:
|
||
inArgument.SetBool(i, api.GoBool(getVal(i+accIdx)))
|
||
}
|
||
}
|
||
}
|
||
|
||
//检索v8绑定
|
||
bindType, name, vType, _, exception := searchBindV8Value(fullName)
|
||
if exception == CVE_ERROR_OK {
|
||
if vType == V8_VALUE_OBJECT || vType == V8_VALUE_ROOT_OBJECT {
|
||
result.set(api.PascalStr(name), uintptr(vType), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
} else {
|
||
if bindType == IS_OBJECT {
|
||
name = name[len(objectRootName)+1:]
|
||
}
|
||
if jsValue, ok := VariableBind.GetValueBind(name); ok {
|
||
jsValue.Lock()
|
||
defer jsValue.UnLock()
|
||
if jsValue.ValueType().Jsv == V8_VALUE_FUNCTION { //func
|
||
var fnInfo = jsValue.getFuncInfo()
|
||
if fnInfo != nil {
|
||
inArgumentAdapter(0, inArgument, fnInfo)
|
||
var outParams, ok = jsValue.invoke(inArgument.ToReflectValue())
|
||
if ok {
|
||
if eventParam.ParamType > 2 {
|
||
var tmpOutParams = make([]reflect.Value, 1)
|
||
if fnInfo.OutNum > 0 {
|
||
tmpOutParams[0] = outParams[fnInfo.OutParamIdx]
|
||
inArgument.ReflectValueConvert(tmpOutParams) //出参转换
|
||
data := inArgument.GetData(0)
|
||
switch GO_VALUE_TYPE(data.VType()) {
|
||
case GO_VALUE_STRING:
|
||
result.set(api.PascalStr(data.GetString()), uintptr(V8_VALUE_STRING), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
case GO_VALUE_INT, GO_VALUE_INT8, GO_VALUE_INT16, GO_VALUE_INT32, GO_VALUE_INT64, GO_VALUE_UINT, GO_VALUE_UINT8, GO_VALUE_UINT16, GO_VALUE_UINT32, GO_VALUE_UINT64, GO_VALUE_UINTPTR:
|
||
result.set(uintptr(data.GetInt32()), uintptr(V8_VALUE_INT), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
case GO_VALUE_FLOAT32, GO_VALUE_FLOAT64:
|
||
var ret = data.GetDouble()
|
||
result.set(uintptr(unsafe.Pointer(&ret)), uintptr(V8_VALUE_DOUBLE), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
case GO_VALUE_BOOL:
|
||
result.set(api.PascalBool(data.GetBool()), uintptr(V8_VALUE_BOOLEAN), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
}
|
||
} else {
|
||
//没有出参
|
||
result.set(0, uintptr(V8_NO_OUT_VALUE), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
}
|
||
}
|
||
} else {
|
||
result.set(api.PascalStr(outParams[0].Interface().(string)), uintptr(V8_VALUE_STRING), 0, uintptr(bindType), uintptr(CVE_ERROR_UNKNOWN_ERROR))
|
||
}
|
||
}
|
||
} else { //field
|
||
inArgs := inArgument.Items()
|
||
if inArgs != nil && len(inArgs) > 0 {
|
||
var (
|
||
errorMsg string
|
||
oldValuePtr unsafe.Pointer
|
||
err error
|
||
)
|
||
//字段赋值
|
||
fieldNewValue := inArgs[0]
|
||
oldValuePtr, err = jsValue.ValueToPtr()
|
||
if err != nil {
|
||
errorMsg = cefErrorMessage(CVE_ERROR_TYPE_NOT_SUPPORTED)
|
||
} else {
|
||
if fieldNewValue.IsString() {
|
||
errorMsg = cefErrorMessage(setPtrValue(jsValue, V8_VALUE_STRING, fieldNewValue.GetString(), 0, 0, false))
|
||
} else if fieldNewValue.IsIntAuto() {
|
||
errorMsg = cefErrorMessage(setPtrValue(jsValue, V8_VALUE_INT, Empty, fieldNewValue.GetInt32(), 0, false))
|
||
} else if fieldNewValue.IsFloatAuto() {
|
||
errorMsg = cefErrorMessage(setPtrValue(jsValue, V8_VALUE_DOUBLE, Empty, 0, fieldNewValue.GetFloat64(), false))
|
||
} else if fieldNewValue.IsBoolean() {
|
||
errorMsg = cefErrorMessage(setPtrValue(jsValue, V8_VALUE_BOOLEAN, Empty, 0, 0, fieldNewValue.GetBool()))
|
||
} else {
|
||
errorMsg = cefErrorMessage(CVE_ERROR_TYPE_NOT_SUPPORTED)
|
||
}
|
||
}
|
||
if Empty == errorMsg {
|
||
result.set(uintptr(oldValuePtr), uintptr(jsValue.ValueType().Jsv), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
} else {
|
||
result.set(api.PascalStr(errorMsg), uintptr(V8_VALUE_STRING), 0, uintptr(bindType), uintptr(CVE_ERROR_TYPE_NOT_SUPPORTED))
|
||
}
|
||
} else {
|
||
//字段取值
|
||
switch jsValue.ValueType().Jsv {
|
||
case V8_VALUE_STRING, V8_VALUE_INT, V8_VALUE_DOUBLE, V8_VALUE_BOOLEAN:
|
||
var ret, err = jsValue.ValueToPtr()
|
||
if err != nil {
|
||
result.set(0, 0, 0, uintptr(bindType), uintptr(CVE_ERROR_TYPE_NOT_SUPPORTED))
|
||
} else {
|
||
result.set(uintptr(ret), uintptr(jsValue.ValueType().Jsv), 0, uintptr(bindType), uintptr(CVE_ERROR_OK))
|
||
}
|
||
default:
|
||
result.set(0, 0, 0, uintptr(bindType), uintptr(CVE_ERROR_TYPE_NOT_SUPPORTED))
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
result.set(0, 0, 0, 0, uintptr(CVE_ERROR_NOT_FOUND_FIELD))
|
||
}
|
||
}
|
||
} else {
|
||
//尝试触发用户自定义ipc事件
|
||
if callback := ipc.IPC.Browser().Events().Get(fullName); callback != nil {
|
||
var (
|
||
channelId = common.StrToInt64(api.GoStr(eventParam.FrameId))
|
||
ipcType IPC_TYPE
|
||
conn net.Conn
|
||
)
|
||
if chn := ipc.IPC.Browser().Channel(channelId); chn != nil {
|
||
ipcType = chn.IPCType
|
||
conn = chn.Conn
|
||
}
|
||
ctx := ipc.NewIPCContext(fullName, eventParam.BrowserId, channelId, ipcType, conn, &ipc.IPCEventMessage{}, &ipc.IPCContextResult{}, inArgument)
|
||
callback(ctx)
|
||
result.set(uintptr(ctx.Result().Data()), uintptr(ctx.Result().VType()), 0, uintptr(IS_COMMON), uintptr(CVE_ERROR_OK))
|
||
} else {
|
||
result.set(0, 0, 0, 0, uintptr(CVE_ERROR_NOT_FOUND_FIELD))
|
||
}
|
||
}
|
||
}
|
||
|
||
// 检索绑定的JsValue
|
||
// 返回值
|
||
//
|
||
// bindType 绑定类型 0通用类型,1对象类型
|
||
// fullName 绑定全名称
|
||
// vType js绑定值类型
|
||
// eventID 事件ID
|
||
// exception 错误码
|
||
func searchBindV8Value(fullName string) (IS_CO, string, V8_JS_VALUE_TYPE, int32, CEF_V8_EXCEPTION) {
|
||
if fullName == "" {
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
var fnArr = strings.Split(fullName, ".")
|
||
var fnArrLen = len(fnArr)
|
||
if len(fnArr) > 0 && fnArr[0] == "window" {
|
||
fnArr = fnArr[1:]
|
||
fnArrLen = len(fnArr)
|
||
}
|
||
if fnArrLen == 0 {
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
//对象类型
|
||
if fnArr[0] == commonRootName {
|
||
if fnArrLen == 1 { //commonRootObject 对象
|
||
fullName = strings.Join(fnArr, ".")
|
||
return IS_COMMON, fullName, V8_VALUE_ROOT_OBJECT, 0, CVE_ERROR_OK
|
||
} else if fnArrLen == 2 {
|
||
if jsValue, ok := VariableBind.GetValueBind(fnArr[1]); ok { //通用类型 fnArr[1] 1是因为 obj.field ,这个field 就是1
|
||
return IS_COMMON, jsValue.Name(), jsValue.ValueType().Jsv, int32(jsValue.getEventId()), CVE_ERROR_OK
|
||
} else {
|
||
//不存在
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
} else {
|
||
//不正确的变量名或不存在
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
} else if fnArr[0] == objectRootName {
|
||
if fnArrLen == 1 {
|
||
//objectRootObject对象
|
||
fullName = strings.Join(fnArr, ".")
|
||
return IS_OBJECT, fullName, V8_VALUE_ROOT_OBJECT, 0, CVE_ERROR_OK
|
||
}
|
||
//对象类型查找关系
|
||
var preObj *objectInfo
|
||
var subObj = objectTI.ObjectInfos
|
||
var faLen = len(fnArr)
|
||
for i := 0; i < faLen; i++ {
|
||
if obj, ok := subObj[fnArr[i]]; ok {
|
||
subObj = obj.SubObjectInfo
|
||
preObj = obj
|
||
} else if i > 0 && i+1 < faLen {
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
}
|
||
if preObj != nil {
|
||
var fieldName = fnArr[fnArrLen-1]
|
||
fullName = strings.Join(fnArr, ".")
|
||
if preObj.ObjName == fieldName {
|
||
//返回object Obj对象
|
||
return IS_OBJECT, fullName, V8_VALUE_OBJECT, 0, CVE_ERROR_OK
|
||
} else {
|
||
//字段 或 函数
|
||
if fieldInfo, ok := preObj.FieldInfos[fieldName]; ok {
|
||
return IS_OBJECT, fullName, fieldInfo.ValueType.Jsv, int32(fieldInfo.EventId), CVE_ERROR_OK
|
||
} else if fnInfo, ok := preObj.FunctionInfos[fieldName]; ok {
|
||
return IS_OBJECT, fullName, V8_VALUE_FUNCTION, int32(fnInfo.EventId), CVE_ERROR_OK
|
||
}
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
} else {
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
} else {
|
||
return 0, "", 0, 0, CVE_ERROR_NOT_FOUND_FIELD
|
||
}
|
||
|
||
}
|
||
|
||
func inArgumentAdapter(argsIdxOffset int, inArgument ipc.IArgumentList, fnInfo *funcInfo) {
|
||
items := inArgument.Items()
|
||
inParamType := fnInfo.InParam
|
||
for i := argsIdxOffset; i < inArgument.Size(); i++ {
|
||
if items[i].IsIntAuto() && inParamType[i-argsIdxOffset].IsGoIntAuto() {
|
||
inArgument.SetIntAuto(i, items[i].GetInt32(), fnInfo.InParam[i-argsIdxOffset].Gov)
|
||
}
|
||
}
|
||
}
|
||
|
||
func outArgumentAdapter(argsIdxOffset int, outArgument ipc.IArgumentList, fnInfo *funcInfo) {
|
||
items := outArgument.Items()
|
||
outParamType := fnInfo.OutParam
|
||
for i := argsIdxOffset; i < outArgument.Size(); i++ {
|
||
if items[i].IsIntAuto() && outParamType[i-argsIdxOffset].IsGoIntAuto() {
|
||
outArgument.SetIntAuto(i, items[i].GetInt32(), fnInfo.InParam[i-argsIdxOffset].Gov)
|
||
}
|
||
}
|
||
}
|
||
|
||
func internalBrowserIPCOnEventInit() {
|
||
var ipcJsBindGetValueSuccess = func(buf *bytes.Buffer, valueType int8, data []byte) {
|
||
//rec
|
||
// eventID []byte 4bit
|
||
//ret
|
||
// isSuccess []byte 1bit
|
||
// valueType []byte 1bit
|
||
// value []byte MaxInt32bit
|
||
binary.Write(buf, binary.BigEndian, true) //成功
|
||
binary.Write(buf, binary.BigEndian, valueType) //字段类型
|
||
binary.Write(buf, binary.BigEndian, data) //字段值
|
||
}
|
||
|
||
var ipcJsBindGetValueFail = func(buf *bytes.Buffer, err CEF_V8_EXCEPTION) {
|
||
binary.Write(buf, binary.BigEndian, false) //失败
|
||
binary.Write(buf, binary.BigEndian, int8(err))
|
||
}
|
||
//var occIdx = ipcAccIdx
|
||
//主进程监听回调
|
||
ipc.IPC.Browser().SetOnEvent(func(event ipc.IEventOn) {
|
||
//var fieldReadWriteLock = new(sync.Mutex)
|
||
//获取字段值-同步
|
||
event.On(ipc.Ln_GET_BIND_FIELD_VALUE, func(context ipc.IIPCContext) {
|
||
args := context.Arguments()
|
||
defer args.Clear()
|
||
fullName := args.GetString(0)
|
||
var jsValue, ok = VariableBind.GetValueBind(fullName)
|
||
buf := &bytes.Buffer{}
|
||
defer buf.Reset()
|
||
if ok {
|
||
jsValue.Lock()
|
||
defer jsValue.UnLock()
|
||
var valueType = int8(jsValue.ValueType().Jsv)
|
||
ipcJsBindGetValueSuccess(buf, valueType, jsValue.Bytes())
|
||
} else {
|
||
ipcJsBindGetValueFail(buf, CVE_ERROR_NOT_FOUND_FIELD)
|
||
}
|
||
context.Response(buf.Bytes())
|
||
buf = nil
|
||
context.Free()
|
||
})
|
||
//设置字段值-同步
|
||
event.On(ipc.Ln_SET_BIND_FIELD_VALUE, func(context ipc.IIPCContext) {
|
||
args := context.Arguments()
|
||
defer args.Clear()
|
||
fullName := args.GetString(0)
|
||
item := args.Item(1)
|
||
newValueType := item.VTypeToJS()
|
||
jsValue, ok := VariableBind.GetValueBind(fullName)
|
||
isSuccess := false
|
||
retArgs := ipc.NewArgumentList()
|
||
defer retArgs.Clear()
|
||
if ok {
|
||
jsValue.Lock()
|
||
defer jsValue.UnLock()
|
||
switch newValueType { //设置值,这里是通用类型只需要知道js里设置的什么类型即可
|
||
case V8_VALUE_STRING:
|
||
isSuccess = Empty == cefErrorMessage(setPtrValue(jsValue, newValueType, item.GetString(), 0, 0, false))
|
||
case V8_VALUE_INT:
|
||
isSuccess = Empty == cefErrorMessage(setPtrValue(jsValue, newValueType, Empty, item.GetInt32(), 0, false))
|
||
case V8_VALUE_DOUBLE:
|
||
isSuccess = Empty == cefErrorMessage(setPtrValue(jsValue, newValueType, Empty, 0, item.GetFloat64(), false))
|
||
case V8_VALUE_BOOLEAN:
|
||
isSuccess = Empty == cefErrorMessage(setPtrValue(jsValue, newValueType, Empty, 0, 0, item.GetBool()))
|
||
}
|
||
} else {
|
||
retArgs.SetInt8(1, int8(CVE_ERROR_NOT_FOUND_FIELD))
|
||
}
|
||
retArgs.SetBool(0, isSuccess)
|
||
context.Response(retArgs.Package())
|
||
context.Free()
|
||
})
|
||
//执行函数-同步
|
||
event.On(ipc.Ln_EXECUTE_BIND_FUNC, func(context ipc.IIPCContext) {
|
||
args := context.Arguments()
|
||
fullName := args.GetString(args.Size() - 1)
|
||
dataItems := args.RangeItems(0, args.Size()-1)
|
||
var inArgument = ipc.NewArgumentList()
|
||
inArgument.SetItems(dataItems)
|
||
var jsValue, ok = VariableBind.GetValueBind(fullName)
|
||
var (
|
||
outParams []reflect.Value
|
||
isSuccess bool
|
||
)
|
||
var buf = &bytes.Buffer{}
|
||
defer buf.Reset()
|
||
if ok {
|
||
jsValue.Lock()
|
||
defer jsValue.UnLock()
|
||
var fnInfo = jsValue.getFuncInfo()
|
||
if fnInfo != nil {
|
||
outParams, isSuccess = jsValue.invoke(inArgument.ToReflectValue())
|
||
inArgument.Clear()
|
||
var outArguments = ipc.NewArgumentList()
|
||
outArguments.ReflectValueConvert(outParams)
|
||
binary.Write(buf, binary.BigEndian, isSuccess)
|
||
binary.Write(buf, binary.BigEndian, outArguments.Package())
|
||
outArguments.Clear()
|
||
} else {
|
||
binary.Write(buf, binary.BigEndian, isSuccess)
|
||
binary.Write(buf, binary.BigEndian, int8(CVE_ERROR_NOT_FOUND_FUNC))
|
||
}
|
||
} else {
|
||
binary.Write(buf, binary.BigEndian, isSuccess)
|
||
binary.Write(buf, binary.BigEndian, int8(CVE_ERROR_NOT_FOUND_FUNC))
|
||
}
|
||
context.Response(buf.Bytes())
|
||
buf = nil
|
||
args.Clear()
|
||
context.Free()
|
||
})
|
||
})
|
||
}
|