mirror of
https://gitee.com/energye/energy.git
synced 2024-11-30 18:57:39 +08:00
419 lines
10 KiB
Go
419 lines
10 KiB
Go
//----------------------------------------
|
|
//
|
|
// Copyright © yanghy. All Rights Reserved.
|
|
//
|
|
// Licensed under GNU General Public License v3.0
|
|
//
|
|
//----------------------------------------
|
|
|
|
package cef
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/energye/energy/common"
|
|
. "github.com/energye/energy/consts"
|
|
"github.com/energye/energy/logger"
|
|
"github.com/energye/golcl/lcl/api"
|
|
"reflect"
|
|
"sync"
|
|
"unsafe"
|
|
)
|
|
|
|
type valueBindInfo struct {
|
|
Name uintptr //string 字段名称
|
|
EventId uintptr //
|
|
BindType uintptr //int32 变量类型 0:string 1:int 2:double 3:bool 4:null 5:undefined 6:object 7:array 8:function
|
|
FnInNum uintptr //int32 入参个数
|
|
FnInParamType uintptr //string 入参变量类型 0,1,2,3,1
|
|
FnOutNum uintptr //int32 出参个数
|
|
FnOutParamType uintptr //string 出参变量类型
|
|
}
|
|
|
|
//绑定到Js的字段
|
|
type ICEFv8Value struct {
|
|
eventId uintptr
|
|
instance uintptr
|
|
ptr unsafe.Pointer
|
|
name string //用于字段或函数名
|
|
value interface{} //值
|
|
valueType V8_JS_VALUE_TYPE //0:string 1:int 2:double 3:bool 4:null 5:undefined 6:object 7:array 8:function
|
|
funcInfo *funcInfo //普通函数信息
|
|
sfi *structFuncInfo //对象函数信息
|
|
isCommonObject IS_CO //通用类型或对象类型 默认通用类型
|
|
that JSValue
|
|
rwLock *sync.Mutex
|
|
}
|
|
|
|
type CEFv8BindRoot struct {
|
|
commonRootName string //ICEFv8Value 通用类型变量属性的所属默认对象名称
|
|
objectRootName string //ICEFv8Value 对象类型变量属性的所属默认对象名称
|
|
}
|
|
|
|
//检查函数是否符合 返回:函数详情
|
|
func checkFunc(fnOf reflect.Type, fnType FN_TYPE) (*funcInfo, error) {
|
|
numIn := fnOf.NumIn() - int(fnType)
|
|
numOut := fnOf.NumOut()
|
|
if numOut > BIND_FUNC_OUT_MAX_SUM {
|
|
//出参个数超出
|
|
return nil, errors.New(fmt.Sprintf("WindowBind function parameter error: the maximum number of function parameters is %d, but the actual number is %d", BIND_FUNC_OUT_MAX_SUM, numOut))
|
|
}
|
|
if numIn > BIND_FUNC_IN_MAX_SUM {
|
|
//入参个数超出
|
|
return nil, errors.New(fmt.Sprintf("WindowBind function parameter error: up to %d function input parameters, actually %d", BIND_FUNC_IN_MAX_SUM, numIn))
|
|
}
|
|
r := new(funcInfo)
|
|
r.InNum = int32(numIn)
|
|
r.OutNum = int32(numOut)
|
|
r.InParam = make([]*vt, numIn, numIn)
|
|
r.FnType = fnType
|
|
var idx = 0
|
|
for i := 0; i < numIn; i++ {
|
|
idx = i + int(fnType)
|
|
inTyp := fnOf.In(idx).Kind().String()
|
|
if jsv, gov := common.ParamType(inTyp); jsv == -1 && gov == -1 {
|
|
//入参参数类型不正确
|
|
return nil, errors.New("WindowBind function parameter error: input parameter type can only be [string int float bool]")
|
|
} else {
|
|
r.InParam[i] = &vt{Jsv: jsv, Gov: gov}
|
|
}
|
|
}
|
|
if numOut > 0 && numOut < 3 {
|
|
r.OutParam = make([]*vt, numOut, numOut)
|
|
for i := 0; i < numOut; i++ {
|
|
outTyp := fnOf.Out(i)
|
|
if jsv, gov := common.ParamType(outTyp.Kind().String()); jsv == -1 && gov == -1 {
|
|
//出参类型错误
|
|
return nil, errors.New("WindowBind function parameter error: output parameter type can only be [string int float bool]")
|
|
} else {
|
|
r.OutParam[i] = &vt{Jsv: jsv, Gov: gov}
|
|
r.OutParamIdx = int32(i)
|
|
}
|
|
}
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (m *ICEFv8Value) Lock() {
|
|
m.rwLock.Lock()
|
|
}
|
|
|
|
func (m *ICEFv8Value) UnLock() {
|
|
m.rwLock.Unlock()
|
|
}
|
|
|
|
//ICEFv8Value isCommon
|
|
func (m *ICEFv8Value) isCommon() bool {
|
|
return m.isCommonObject == IS_COMMON
|
|
}
|
|
|
|
func (m *ICEFv8Value) setThat(that JSValue) {
|
|
m.that = that
|
|
}
|
|
|
|
func (m *ICEFv8Value) Bytes() []byte {
|
|
var iValue interface{}
|
|
if m.isCommon() {
|
|
iValue = m.value
|
|
} else { //object
|
|
if refValue, ok := m.value.(*reflect.Value); ok {
|
|
iValue = refValue.Interface()
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
switch m.valueType {
|
|
case V8_VALUE_STRING:
|
|
return common.StringToBytes(iValue.(string))
|
|
case V8_VALUE_INT:
|
|
if v, err := common.ValueToInt32(iValue); err == nil {
|
|
return common.Int32ToBytes(v)
|
|
} else {
|
|
return nil
|
|
}
|
|
case V8_VALUE_DOUBLE:
|
|
if v, err := common.ValueToFloat64(iValue); err == nil {
|
|
return common.Float64ToBytes(v)
|
|
} else {
|
|
return nil
|
|
}
|
|
case V8_VALUE_BOOLEAN:
|
|
if v, err := common.ValueToBool(iValue); err == nil {
|
|
return []byte{common.BoolToByte(v)}
|
|
} else {
|
|
return nil
|
|
}
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (m *ICEFv8Value) ValueToPtr() (unsafe.Pointer, error) {
|
|
var iValue interface{}
|
|
if m.isCommon() {
|
|
iValue = m.value
|
|
} else { //object
|
|
if refValue, ok := m.value.(*reflect.Value); ok {
|
|
iValue = refValue.Interface()
|
|
} else {
|
|
return nil, errors.New("object转换reflect.Value失败")
|
|
}
|
|
}
|
|
switch m.valueType {
|
|
case V8_VALUE_STRING:
|
|
return unsafe.Pointer(api.PascalStr(iValue.(string))), nil
|
|
//return GoStrToDStrPointer(iValue.(string)), nil
|
|
case V8_VALUE_INT:
|
|
if v, err := common.ValueToInt32(iValue); err == nil {
|
|
return unsafe.Pointer(uintptr(v)), nil
|
|
} else {
|
|
return nil, err
|
|
}
|
|
case V8_VALUE_DOUBLE:
|
|
if v, err := common.ValueToFloat64(iValue); err == nil {
|
|
return unsafe.Pointer(&v), nil
|
|
} else {
|
|
return nil, err
|
|
}
|
|
case V8_VALUE_BOOLEAN:
|
|
if v, err := common.ValueToBool(iValue); err == nil {
|
|
return unsafe.Pointer(api.PascalBool(v)), nil
|
|
} else {
|
|
return nil, err
|
|
}
|
|
default:
|
|
return nil, errors.New("unsupported type")
|
|
}
|
|
}
|
|
|
|
func (m *ICEFv8Value) SetAnyValue(value interface{}) error {
|
|
switch common.JSValueAssertType(value) {
|
|
case V8_VALUE_STRING:
|
|
m.setValueType(V8_VALUE_STRING)
|
|
case V8_VALUE_INT:
|
|
m.setValueType(V8_VALUE_INT)
|
|
case V8_VALUE_DOUBLE:
|
|
m.setValueType(V8_VALUE_DOUBLE)
|
|
case V8_VALUE_BOOLEAN:
|
|
m.setValueType(V8_VALUE_BOOLEAN)
|
|
default:
|
|
return errors.New(cefErrorMessage(CVE_ERROR_TYPE_NOT_SUPPORTED))
|
|
}
|
|
m.setValue(value)
|
|
return nil
|
|
}
|
|
|
|
func (m *ICEFv8Value) getFuncInfo() *funcInfo {
|
|
return m.funcInfo
|
|
}
|
|
|
|
func (m *ICEFv8Value) Instance() uintptr {
|
|
return m.instance
|
|
}
|
|
|
|
func (m *ICEFv8Value) Ptr() unsafe.Pointer {
|
|
return m.ptr
|
|
}
|
|
|
|
func (m *ICEFv8Value) Name() string {
|
|
return m.name
|
|
}
|
|
|
|
func (m *ICEFv8Value) setName(name string) {
|
|
m.name = name
|
|
}
|
|
|
|
func (m *ICEFv8Value) getValue() interface{} {
|
|
return m.value
|
|
}
|
|
|
|
func (m *ICEFv8Value) setValue(value interface{}) {
|
|
m.value = value
|
|
}
|
|
|
|
func (m *ICEFv8Value) ValueType() V8_JS_VALUE_TYPE {
|
|
return m.valueType
|
|
}
|
|
|
|
func (m *ICEFv8Value) setValueType(vType V8_JS_VALUE_TYPE) {
|
|
m.valueType = vType
|
|
}
|
|
|
|
func (m *ICEFv8Value) setPtr(ptr unsafe.Pointer) {
|
|
m.ptr = ptr
|
|
}
|
|
|
|
func (m *ICEFv8Value) setInstance(instance uintptr) {
|
|
m.instance = instance
|
|
}
|
|
|
|
func (m *ICEFv8Value) StringValue() (string, error) {
|
|
if m.IsString() {
|
|
return common.ValueToString(m.value)
|
|
}
|
|
return "", errors.New("failed to get a string value")
|
|
}
|
|
|
|
func (m *ICEFv8Value) IntegerValue() (int32, error) {
|
|
if m.IsInteger() {
|
|
return common.ValueToInt32(m.value)
|
|
}
|
|
return 0, errors.New("failed to get a integer value")
|
|
}
|
|
|
|
func (m *ICEFv8Value) DoubleValue() (float64, error) {
|
|
if m.IsDouble() {
|
|
return common.ValueToFloat64(m.value)
|
|
}
|
|
return 0, errors.New("failed to get a double value")
|
|
}
|
|
|
|
func (m *ICEFv8Value) BooleanValue() (bool, error) {
|
|
if m.IsBool() {
|
|
return common.ValueToBool(m.value)
|
|
}
|
|
return false, errors.New("failed to get a boolean value")
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsString() bool {
|
|
return m.valueType == V8_VALUE_STRING
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsInteger() bool {
|
|
return m.valueType == V8_VALUE_INT
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsDouble() bool {
|
|
return m.valueType == V8_VALUE_DOUBLE
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsBool() bool {
|
|
return m.valueType == V8_VALUE_BOOLEAN
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsArray() bool {
|
|
return m.valueType == V8_VALUE_ARRAY
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsObject() bool {
|
|
return m.valueType == V8_VALUE_OBJECT
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsFunction() bool {
|
|
return m.valueType == V8_VALUE_FUNCTION
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsNull() bool {
|
|
return m.valueType == V8_VALUE_NULL
|
|
}
|
|
|
|
func (m *ICEFv8Value) IsUndefined() bool {
|
|
return m.valueType == V8_VALUE_UNDEFINED
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsString() (*JSString, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSString); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to String")
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsInteger() (*JSInteger, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSInteger); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to Integer")
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsDouble() (*JSDouble, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSDouble); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to Double")
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsBoolean() (*JSBoolean, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSBoolean); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to Boolean")
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsArray() (*JSArray, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSArray); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to Array")
|
|
}
|
|
|
|
func (m *ICEFv8Value) AsFunction() (*JSFunction, error) {
|
|
if m.that != nil {
|
|
if v, ok := m.that.(*JSFunction); ok {
|
|
return v, nil
|
|
}
|
|
}
|
|
return nil, errors.New("unable to cast to Function")
|
|
}
|
|
|
|
func (m *ICEFv8Value) invoke(inParams []reflect.Value) (outParams []reflect.Value, success bool) {
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
logger.Error("V8BindFuncCallbackHandler recover:", err)
|
|
outParams = []reflect.Value{reflect.ValueOf(err.(error).Error())}
|
|
success = false
|
|
}
|
|
}()
|
|
if m.isCommon() {
|
|
outParams = reflect.ValueOf(m.value).Call(inParams)
|
|
} else {
|
|
outParams = m.sfi.Method.Call(inParams)
|
|
}
|
|
return outParams, true
|
|
}
|
|
|
|
//ICEFv8Value newICEFv8Value
|
|
func newICEFv8Value(eventId uintptr, fullParentName, name string, value interface{}, sfi *structFuncInfo, valueType V8_JS_VALUE_TYPE, isCommonObject IS_CO) JSValue {
|
|
jsValueBind := new(ICEFv8Value)
|
|
jsValueBind.rwLock = new(sync.Mutex)
|
|
jsValueBind.ptr = unsafe.Pointer(&jsValueBind)
|
|
jsValueBind.instance = uintptr(jsValueBind.ptr)
|
|
jsValueBind.eventId = eventId
|
|
jsValueBind.name = name
|
|
jsValueBind.value = value
|
|
if sfi != nil {
|
|
jsValueBind.funcInfo = sfi.funcInfo
|
|
}
|
|
jsValueBind.sfi = sfi
|
|
jsValueBind.valueType = valueType
|
|
jsValueBind.isCommonObject = isCommonObject
|
|
|
|
//putValueBind(jsValueBind.eventId, jsValueBind)
|
|
VariableBind.putValueBind(fmt.Sprintf("%s.%s", fullParentName, name), jsValueBind)
|
|
return jsValueBind
|
|
}
|
|
|
|
//ICEFv8Value Pointer
|
|
func (m *ICEFv8Value) Pointer() unsafe.Pointer {
|
|
return m.ptr
|
|
}
|
|
|
|
//ICEFv8Value setEventId
|
|
func (m *ICEFv8Value) setEventId(eventId uintptr) {
|
|
m.eventId = eventId
|
|
}
|
|
|
|
//ICEFv8Value getEventId
|
|
func (m *ICEFv8Value) getEventId() uintptr {
|
|
return m.eventId
|
|
}
|