energy/cef/vars.go
2023-03-02 18:47:39 +08:00

334 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// energy 变量相关
package cef
import (
"errors"
"fmt"
"github.com/energye/energy/common"
. "github.com/energye/energy/consts"
"reflect"
"sync"
"unsafe"
)
var (
nullptr unsafe.Pointer = nil //
isMainProcess, isRenderProcess bool //
)
type initBindVariableCallback func(browser *ICefBrowser, frame *ICefFrame, bind IProvisionalBindStorage)
// VariableBind 变量绑定
var VariableBind IProvisionalBindStorage
type IProvisionalBindStorage interface {
VariableCreateCallback(callback func(browser *ICefBrowser, frame *ICefFrame, bind IProvisionalBindStorage))
NewString(name, value string) *JSString //通用类型 - 默认: string
NewInteger(name string, value int32) *JSInteger //通用类型 - 默认: integer
NewDouble(name string, value float64) *JSDouble //通用类型 - 默认: double
NewBoolean(name string, value bool) *JSBoolean //通用类型 - 默认: boolean
NewNull(name string) *JSNull //通用类型 - 默认: null
NewUndefined(name string) *JSUndefined //通用类型 - 默认: undefined
NewFunction(name string, fn interface{}) error //固定类型 - function
NewObjects(objects ...interface{}) //固定类型 - object - struct
Bind(name string, bind interface{}) error //固定类型 - 所有支持类型
bindValue(fullName string) (JSValue, bool) //
binds() map[string]JSValue //
bindCount() int //
callVariableBind(browser *ICefBrowser, frame *ICefFrame) //
addBind(fullName string, value JSValue) //
}
type variableBind struct {
initBindVariableCallback initBindVariableCallback //
bindMapping map[string]JSValue //所有绑定变量属性或函数集合
lock sync.Mutex //add bind, remove bind lock
}
func init() {
isMainProcess = common.Args.IsMain()
isRenderProcess = common.Args.IsRender()
VariableBind = &variableBind{bindMapping: make(map[string]JSValue)}
fmt.Println("isMainProcess:", isMainProcess, "isRenderProcess:", isRenderProcess)
}
func (m *variableBind) addBind(fullName string, value JSValue) {
m.lock.Lock()
defer m.lock.Unlock()
if _, ok := m.bindMapping[fullName]; !ok {
m.bindMapping[fullName] = value
}
}
func (m *variableBind) removeBind(fullName string) {
m.lock.Lock()
defer m.lock.Unlock()
delete(m.bindMapping, fullName)
}
func (m *variableBind) bindValue(fullName string) (JSValue, bool) {
value, ok := m.bindMapping[fullName]
return value, ok
}
func (m *variableBind) binds() map[string]JSValue {
return m.bindMapping
}
func (m *variableBind) bindCount() int {
return len(m.bindMapping)
}
// VariableCreateCallback
//
// # Go 和 javaScript 的函数或变量绑定声明初始函数
//
// 在 javaScript 中调用Go中的函数,变量)需要在此回调函数中绑定
//
// 主进程和子进程
func (m *variableBind) VariableCreateCallback(callback func(browser *ICefBrowser, frame *ICefFrame, bind IProvisionalBindStorage)) {
m.initBindVariableCallback = callback
}
// 调用变量绑定回调函数
//
// 在主进程和渲染进程创建时调用
func (m *variableBind) callVariableBind(browser *ICefBrowser, frame *ICefFrame) {
if m.initBindVariableCallback != nil {
m.initBindVariableCallback(browser, frame, m)
}
}
// NewString V8Value
func (m *variableBind) NewString(name, value string) *JSString {
jsValueBind := new(JSString)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = value
jsValueBind.valueType.Jsv = V8_VALUE_STRING
jsValueBind.valueType.Gov = GO_VALUE_STRING
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewInteger V8Value
func (m *variableBind) NewInteger(name string, value int32) *JSInteger {
jsValueBind := new(JSInteger)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = value
jsValueBind.valueType.Jsv = V8_VALUE_INT
jsValueBind.valueType.Gov = GO_VALUE_INT32
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewDouble V8Value
func (m *variableBind) NewDouble(name string, value float64) *JSDouble {
jsValueBind := new(JSDouble)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = value
jsValueBind.valueType.Jsv = V8_VALUE_DOUBLE
jsValueBind.valueType.Gov = GO_VALUE_FLOAT64
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewBool V8Value
func (m *variableBind) NewBoolean(name string, value bool) *JSBoolean {
jsValueBind := new(JSBoolean)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = value
jsValueBind.valueType.Jsv = V8_VALUE_BOOLEAN
jsValueBind.valueType.Gov = GO_VALUE_BOOL
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewNull V8Value
func (m *variableBind) NewNull(name string) *JSNull {
jsValueBind := new(JSNull)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = "null"
jsValueBind.valueType.Jsv = V8_VALUE_NULL
jsValueBind.valueType.Gov = GO_VALUE_NIL
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewUndefined V8Value
func (m *variableBind) NewUndefined(name string) *JSUndefined {
jsValueBind := new(JSUndefined)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = "undefined"
jsValueBind.valueType.Jsv = V8_VALUE_UNDEFINED
jsValueBind.valueType.Gov = GO_VALUE_STRING
m.bindValueHandle(jsValueBind)
return jsValueBind
}
// NewFunction V8Value
//
// 绑定 定义的普通函数 prefix default struct name
func (m *variableBind) NewFunction(name string, fn interface{}) error {
if gov, _ := common.FieldReflectType(fn); gov == GO_VALUE_FUNC {
if info, err := checkFunc(reflect.TypeOf(fn), FN_TYPE_COMMON); err == nil {
jsValueBind := new(JSFunction)
jsValueBind.valueType = new(VT)
jsValueBind.rwLock = new(sync.Mutex)
jsValueBind.name = name
jsValueBind.value = fn
jsValueBind.valueType.Jsv = V8_VALUE_FUNCTION
jsValueBind.valueType.Gov = GO_VALUE_FUNC
jsValueBind.funcInfo = info
m.bindValueHandle(jsValueBind)
return nil
} else {
return err
}
}
return errors.New("创建的函数不是函数类型")
}
// V8Value bindValueHandle
func (m *variableBind) bindValueHandle(jsValue JSValue) {
jsValue.setPtr(unsafe.Pointer(&jsValue))
jsValue.setInstance(uintptr(jsValue.Ptr()))
jsValue.setEventId(uintptr(__bind_id()))
jsValue.setThat(jsValue)
m.addBind(jsValue.Name(), jsValue)
}
// NewObjects V8Value
//
// 对象类型变量和对象函数绑定
func (m *variableBind) NewObjects(objects ...interface{}) {
bindObject(objects...)
}
// Bind V8Value
//
// 变量和函数绑定, 在Go中定义绑定到JS中
//
// 支持类型 String = string , Integer = int32 , Double = float64, Boolean = bool, Function = func, ObjectInfos = struct | map, Array = Slice
//
// 返回nil表示绑定成功
func (m *variableBind) Bind(name string, bind interface{}) error {
if isMainProcess || isRenderProcess {
typ := reflect.TypeOf(bind)
kind := typ.Kind()
if kind != reflect.Ptr && kind != reflect.Func {
return errors.New(fmt.Sprintf("绑定字段 %s: 应传递绑定变量指针", name))
}
var (
gov GO_VALUE_TYPE
jsv V8_JS_VALUE_TYPE
value *V8Value
)
if kind == reflect.Func {
gov = GO_VALUE_FUNC
jsv = V8_VALUE_FUNCTION
} else {
gov, jsv = common.FieldReflectType(typ.Elem())
}
fmt.Println("FieldReflectType:", gov, jsv)
if gov == -1 || jsv == -1 {
return errors.New("类型错误, 支持类型: string, int32, float64, bool, func, struct, map, slice")
}
value = &V8Value{
name: name,
rwLock: new(sync.Mutex),
valueType: &VT{
Jsv: jsv,
Gov: gov,
},
//isCommonObject: IS_OBJECT,
//eventId: uintptr(__bind_id()),
}
//分解类型
if jsv == V8_VALUE_FUNCTION && isMainProcess { //function
if info, err := checkFunc(reflect.TypeOf(bind), FN_TYPE_OBJECT); err == nil {
value.funcInfo = info
value.ptr = unsafe.Pointer(&bind)
} else {
return err
}
} else if jsv == V8_VALUE_OBJECT { //object
if gov == GO_VALUE_STRUCT { // object - struct
} else if gov == GO_VALUE_MAP { // object - map
}
} else if jsv == V8_VALUE_ARRAY { //array
} else if isMainProcess { //field
switch jsv {
case V8_VALUE_STRING:
value.ptr = unsafe.Pointer(bind.(*string))
case V8_VALUE_INT:
switch gov {
case GO_VALUE_INT:
value.ptr = unsafe.Pointer(bind.(*int))
case GO_VALUE_INT8:
value.ptr = unsafe.Pointer(bind.(*int8))
case GO_VALUE_INT16:
value.ptr = unsafe.Pointer(bind.(*int16))
case GO_VALUE_INT32:
value.ptr = unsafe.Pointer(bind.(*int32))
case GO_VALUE_INT64:
value.ptr = unsafe.Pointer(bind.(*int64))
case GO_VALUE_UINT:
value.ptr = unsafe.Pointer(bind.(*uint))
case GO_VALUE_UINT8:
value.ptr = unsafe.Pointer(bind.(*uint8))
case GO_VALUE_UINT16:
value.ptr = unsafe.Pointer(bind.(*uint16))
case GO_VALUE_UINT32:
value.ptr = unsafe.Pointer(bind.(*uint32))
case GO_VALUE_UINT64:
value.ptr = unsafe.Pointer(bind.(*uint64))
case GO_VALUE_UINTPTR:
value.ptr = unsafe.Pointer(bind.(*uintptr))
}
case V8_VALUE_DOUBLE:
if gov == GO_VALUE_FLOAT32 {
value.ptr = unsafe.Pointer(bind.(*float32))
} else {
value.ptr = unsafe.Pointer(bind.(*float64))
}
case V8_VALUE_BOOLEAN:
value.ptr = unsafe.Pointer(bind.(*bool))
default:
return errors.New(name + ": 不支持的绑定类型")
}
}
if isMainProcess {
value.instance = uintptr(value.ptr)
value.value = bind
value.that = value
}
m.addBind(name, value)
}
return nil
}