upgrade-dev v2.3.41

This commit is contained in:
杨红岩 2023-03-27 12:03:36 +08:00
parent 0af7e5c44f
commit 47ba9bad8b
6 changed files with 412 additions and 43 deletions

View File

@ -13,6 +13,7 @@ package bind
import (
"container/list"
"fmt"
"github.com/energye/energy/pkgs/json"
"sync"
"unsafe"
)
@ -32,10 +33,14 @@ type v8bind struct {
// value: 值
func (m *v8bind) Set(name string, value JSValue) {
if id, ok := m.hasFieldCollection[name]; ok {
m.Remove(id)
old := m.Remove(id)
id = m.Add(value)
value.setId(id)
m.hasFieldCollection[name] = id
switch old.(type) {
case JSValue:
old.(JSValue).setId(id)
}
} else {
id = m.Add(value)
value.setId(id)
@ -59,10 +64,13 @@ func (m *v8bind) Get(id uintptr) *list.Element {
return (*list.Element)(unsafe.Pointer(id))
}
func (m *v8bind) Remove(id uintptr) {
func (m *v8bind) Remove(id uintptr) any {
if v := m.Get(id); v != nil {
m.fieldCollection.Remove(v)
r := m.fieldCollection.Remove(v)
v.Value = nil
return r
}
return nil
}
func (m *v8bind) Binds() map[string]JSValue {
@ -75,7 +83,73 @@ func GetBinds(fn func(binds map[string]JSValue)) {
}
func Test() {
stringKey := NewString("stringKey", "字符串值")
fmt.Println("stringKey", stringKey, stringKey.IsString())
stringKey = NewString("stringKey", "字符串值")
//字段
stringKey0 := NewString("stringKey", "字符串值0")
fmt.Println("stringKey", stringKey0, stringKey0.Value())
stringKey1 := NewString("stringKey", "字符串值1")
integerKey := NewInteger("integerKey", 1000)
fmt.Println("stringKey", stringKey0)
fmt.Println("stringKey", stringKey1, stringKey1.Value())
fmt.Println("integerKey", integerKey.Value())
integerKey.SetValue("变成字符串")
fmt.Println("integerKey", integerKey.AsString().Value())
integerKey.SetValue(true)
boolField := integerKey.AsBoolean()
fmt.Println("boolField", boolField.Value())
fmt.Println("boolField", bind.GetJSValue(boolField.Id()).AsBoolean().Value())
boolField.SetValue(false)
fmt.Println("boolField", bind.GetJSValue(boolField.Id()).AsBoolean().Value())
fmt.Println(bind.fieldCollection.Len())
//函数
funcKey := NewFunction("funcKey", func(in1 string) {
fmt.Println(in1)
})
inArgument := json.NewJSONArray(nil)
inArgument.Add("字符串参数")
funcKey.Invoke(inArgument)
//对象
type objectDemo1 struct {
Key1 string
Key2 string
}
type objectDemo2 struct {
Key1 string
Key2 string
Key3 int
}
type object struct {
Key1 string
Key2 string
Key3 int
Key4 float64
Key5 bool
Key6 *objectDemo1
Key7 objectDemo2
}
var testObj = &object{
Key1: "value1",
Key2: "value2",
Key3: 333,
Key4: 555.3,
Key5: true,
//Key6: &objectDemo1{},
}
objectKey := NewObject(testObj)
fmt.Println(objectKey.JSONString())
objectKey.Set("Key1", "值1")
objectKey.Set("Key2", "值2")
objectKey.Set("Key3", 4444)
objectKey.Set("Key4", 9999.99)
objectKey.Set("Key5", false)
objectKey.Set("Key6", &objectDemo1{})
objectKey.Set("Key7", objectDemo2{Key1: "值值"})
fmt.Println(objectKey.JSONString())
objectKey1 := objectKey.Get("Key1")
fmt.Println(objectKey1.Name())
objectKey1.SetValue("objectKey1设置新值 ")
objectKey.Get("Key6")
fmt.Println(objectKey.JSONString())
}

View File

@ -19,6 +19,7 @@ import (
"github.com/energye/energy/common"
"github.com/energye/energy/consts"
"github.com/energye/energy/pkgs/json"
"reflect"
)
const (
@ -36,6 +37,7 @@ var (
type JSValue interface {
Name() string //当前变量绑定的名称
Bytes() []byte //变量值转换为字节
JSONString() string //变量值转换为JSON String
SetValue(value any) //设置新值
IsInteger() bool //是否 Integer
IsDouble() bool //是否 Double
@ -57,17 +59,20 @@ type JSValue interface {
AsFunction() JSFunction //转换为 Function 失败返回 nil
AsV8Value() JSValue //转换为 JSValue
setId(id uintptr)
Id() uintptr
free()
}
// V8Value 绑定到JS的字段
type V8Value struct {
id uintptr
name string
rv *reflect.Value
value json.JSON
}
func init() {
isMainProcess = common.Args.IsMain()
isMainProcess = common.Args.IsMain() //TODO dev
}
// Bytes 值转换为字节
@ -75,16 +80,48 @@ func (m *V8Value) Bytes() []byte {
return m.value.Bytes()
}
func (m *V8Value) JSONString() string {
return string(m.Bytes())
}
// SetValue 设置值
// 函数不能设置值
func (m *V8Value) SetValue(value any) {
if isMainProcess {
m.value.SetValue(value)
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
switch kind {
case reflect.Struct:
v := new(jsObject)
v.name = m.name
v.value = &json.JsonData{T: consts.GO_VALUE_STRUCT, V: value, S: 0}
v.rv = &rv
bind.Set(m.name, v)
case reflect.Slice:
case reflect.Func:
v := new(jsFunction)
v.name = m.name
v.value = &json.JsonData{T: consts.GO_VALUE_FUNC, V: value, S: 0}
v.rv = &rv
bind.Set(m.name, v)
default:
if m.rv != nil {
m.rv.Set(rv)
}
m.value.SetValue(value)
}
}
}
func (m *V8Value) setId(id uintptr) {
m.id = id
}
func (m *V8Value) Id() uintptr {
return m.id
}
func (m *V8Value) Name() string {
return m.name
@ -111,7 +148,7 @@ func (m *V8Value) IsArray() bool {
}
func (m *V8Value) IsObject() bool {
return m.value.IsObject()
return m.value.Type() == consts.GO_VALUE_STRUCT
}
func (m *V8Value) IsFunction() bool {
@ -132,7 +169,6 @@ func (m *V8Value) AsString() JSString {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -144,7 +180,6 @@ func (m *V8Value) AsInteger() JSInteger {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -156,7 +191,6 @@ func (m *V8Value) AsDouble() JSDouble {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -168,7 +202,6 @@ func (m *V8Value) AsBoolean() JSBoolean {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -180,7 +213,6 @@ func (m *V8Value) AsNull() JSNull {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -192,7 +224,6 @@ func (m *V8Value) AsUndefined() JSUndefined {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -204,7 +235,6 @@ func (m *V8Value) AsFunction() JSFunction {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -216,7 +246,6 @@ func (m *V8Value) AsObject() JSObject {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -228,7 +257,6 @@ func (m *V8Value) AsArray() JSArray {
v.name = m.name
v.value = m.value.JsonData()
bind.Set(m.name, v)
m.free()
return v
}
return nil // default
@ -240,6 +268,7 @@ func (m *V8Value) AsV8Value() JSValue {
func (m *V8Value) free() {
if m.value != nil {
m.id = 0
m.name = ""
m.value.Free()
m.value = nil
@ -338,29 +367,42 @@ func NewFunction(name string, fn any) JSFunction {
if !isMainProcess {
fn = nil
}
rv := reflect.ValueOf(fn)
if rv.Kind() != reflect.Func {
return nil
}
v := new(jsFunction)
v.name = name
v.value = &json.JsonData{T: consts.GO_VALUE_FUNC, V: fn, S: 0}
v.value = &json.JsonData{T: consts.GO_VALUE_FUNC, V: &rv, S: 0}
bind.Set(name, v)
return v
}
// NewObject GO&JS 对象类型
func NewObject(name string, object any) JSObject {
if name == "" {
// NewObject GO&JS 对象类型 &struct{} 仅结构
func NewObject(object any) JSObject {
if object == nil {
return nil
}
if !isMainProcess {
object = nil
}
if vv := json.NewJSONObject(object); vv != nil {
v := new(jsObject)
v.name = name
v.value = vv.JsonData()
bind.Set(name, v)
return v
rv := reflect.ValueOf(object)
kind := rv.Kind()
//必须是指针
if kind != reflect.Ptr {
return nil
}
return nil
kind = rv.Elem().Kind()
//必须是结构
if kind != reflect.Struct {
return nil
}
v := new(jsObject)
v.name = rv.Type().Elem().Name()
v.value = &json.JsonData{T: consts.GO_VALUE_STRUCT, V: object, S: 0}
v.rv = &rv
bind.Set(v.name, v)
return v
}
// NewArray GO&JS 数组类型

View File

@ -11,20 +11,142 @@
// V8 JSValue JSFunction 类型实现
package bind
import (
"github.com/energye/energy/pkgs/json"
jsoniter "github.com/json-iterator/go"
"reflect"
)
type JSFunction interface {
JSValue
AsFunction() JSFunction
Value() JSFunction
// Invoke 调用函数,入参: 以参数列表形式传入参数, 出参: 以参数列表形式返回参数
// 如果参数类型或数量不匹配这些参数将以类型的默认值传入
Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray)
}
type jsFunction struct {
V8Value
rv *reflect.Value
}
func (m *jsFunction) AsFunction() JSFunction {
return m
}
func (m *jsFunction) Value() JSFunction {
return nil
func (m *jsFunction) Invoke(argumentList json.JSONArray) (resultArgument json.JSONArray) {
resultArgument = nil
if m.IsFunction() {
rv, ok := m.value.Data().(*reflect.Value)
if !ok {
return
}
var (
argsSize int
inArgsValues []reflect.Value
)
if argumentList != nil {
argsSize = argumentList.Size()
}
rt := rv.Type()
inArgsCount := rt.NumIn()
inArgsValues = make([]reflect.Value, inArgsCount)
for i := 0; i < inArgsCount; i++ {
inType := rt.In(i)
if i < argsSize {
argsValue := argumentList.GetByIndex(i)
if argsValue != nil {
switch inType.Kind() {
case reflect.String:
inArgsValues[i] = reflect.ValueOf(argsValue.String())
case reflect.Int:
inArgsValues[i] = reflect.ValueOf(argsValue.Int())
case reflect.Int8:
inArgsValues[i] = reflect.ValueOf(int8(argsValue.Int()))
case reflect.Int16:
inArgsValues[i] = reflect.ValueOf(int16(argsValue.Int()))
case reflect.Int32:
inArgsValues[i] = reflect.ValueOf(int32(argsValue.Int()))
case reflect.Int64:
inArgsValues[i] = reflect.ValueOf(int64(argsValue.Int()))
case reflect.Uint:
inArgsValues[i] = reflect.ValueOf(uint(argsValue.Int()))
case reflect.Uint8:
inArgsValues[i] = reflect.ValueOf(uint8(argsValue.Int()))
case reflect.Uint16:
inArgsValues[i] = reflect.ValueOf(uint16(argsValue.Int()))
case reflect.Uint32:
inArgsValues[i] = reflect.ValueOf(uint32(argsValue.Int()))
case reflect.Uint64:
inArgsValues[i] = reflect.ValueOf(uint64(argsValue.Int()))
case reflect.Uintptr:
inArgsValues[i] = reflect.ValueOf(uintptr(argsValue.Int()))
case reflect.Float32:
inArgsValues[i] = reflect.ValueOf(float32(argsValue.Float()))
case reflect.Float64:
inArgsValues[i] = reflect.ValueOf(argsValue.Float())
case reflect.Bool:
inArgsValues[i] = reflect.ValueOf(argsValue.Bool())
case reflect.Struct:
if argsValue.IsObject() {
// struct
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
v := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, v.Interface()); err == nil {
inArgsValues[i] = v.Elem()
}
}
}
case reflect.Map:
if argsValue.IsObject() {
// map key=string : value != interface
if inType.Elem().Kind() != reflect.Interface {
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
vv := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, vv.Interface()); err == nil {
inArgsValues[i] = vv.Elem()
}
}
} else {
inArgsValues[i] = reflect.ValueOf(argsValue.Data())
}
}
case reflect.Slice:
if argsValue.IsArray() {
// slice value != interface
if inType.Elem().Kind() != reflect.Interface {
if jsonBytes := argsValue.Bytes(); jsonBytes != nil {
vv := reflect.New(inType)
if err := jsoniter.Unmarshal(jsonBytes, vv.Interface()); err == nil {
inArgsValues[i] = vv.Elem()
}
}
} else {
inArgsValues[i] = reflect.ValueOf(argsValue.Data())
}
}
}
}
}
if !inArgsValues[i].IsValid() {
inArgsValues[i] = reflect.New(inType).Elem()
}
}
// call
resultValues := rv.Call(inArgsValues)
if len(resultValues) > 0 {
// call result
resultArgument = json.NewJSONArray(nil)
for _, result := range resultValues {
res := result.Interface()
switch res.(type) {
case error:
resultArgument.Add(res.(error).Error())
default:
resultArgument.Add(res)
}
}
}
}
return
}

View File

@ -14,7 +14,7 @@ package bind
type JSInteger interface {
JSValue
AsInteger() JSInteger
Value() int32
Value() int
}
type jsInteger struct {
@ -25,6 +25,6 @@ func (m *jsInteger) AsInteger() JSInteger {
return m
}
func (m *jsInteger) Value() int32 {
return int32(m.value.Int())
func (m *jsInteger) Value() int {
return m.value.Int()
}

View File

@ -11,22 +11,157 @@
// V8 JSValue JSObject 实现
package bind
import "github.com/energye/energy/pkgs/json"
import (
"fmt"
"github.com/energye/energy/consts"
"github.com/energye/energy/pkgs/json"
"reflect"
"strings"
"unsafe"
)
type JSObject interface {
JSValue
AsObject() JSObject
Value() json.JSONObject
Value() any
Get(fieldName string) JSValue
Set(fieldName string, value any)
}
type jsObject struct {
V8Value
pName string
}
func (m *jsObject) AsObject() JSObject {
return m
}
func (m *jsObject) Value() json.JSONObject {
return m.value.JSONObject()
func (m *jsObject) Value() any {
if m.IsObject() {
return m.value.Data()
}
return nil
}
func (m *jsObject) Get(fieldName string) JSValue {
if fieldName == "" {
return nil
}
if m.IsObject() {
rv := m.rv.Elem().FieldByName(fieldName)
if rv.IsZero() {
return nil
}
kind := rv.Kind()
if kind == reflect.Ptr {
kind = rv.Elem().Kind()
}
fmt.Println("get kind", kind)
switch kind {
case reflect.String:
v := new(jsObject)
v.name = fieldName
v.pName = m.name
v.value = &json.JsonData{T: consts.GO_VALUE_STRING, V: rv.Interface(), S: 0}
v.rv = &rv
var build strings.Builder
build.WriteString(v.pName)
build.WriteString(".")
build.WriteString(v.name)
bind.Set(build.String(), v)
build.Reset()
return v
}
}
return nil
}
func (m *jsObject) Set(fieldName string, value any) {
if m.IsObject() {
field := m.rv.Elem().FieldByName(fieldName)
switch field.Kind() {
case reflect.String:
if v, ok := value.(string); ok {
*(*string)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int:
if v, ok := value.(int); ok {
*(*int)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int8:
if v, ok := value.(int8); ok {
*(*int8)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int16:
if v, ok := value.(int16); ok {
*(*int16)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int32:
if v, ok := value.(int32); ok {
*(*int32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Int64:
if v, ok := value.(int64); ok {
*(*int64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint:
if v, ok := value.(uint); ok {
*(*uint)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint8:
if v, ok := value.(uint8); ok {
*(*uint8)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint16:
if v, ok := value.(uint16); ok {
*(*uint16)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint32:
if v, ok := value.(uint32); ok {
*(*uint32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Uint64:
if v, ok := value.(uint64); ok {
*(*uint64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Float64:
if v, ok := value.(float64); ok {
*(*float64)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Float32:
if v, ok := value.(float32); ok {
*(*float32)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Bool:
if v, ok := value.(bool); ok {
*(*bool)(unsafe.Pointer(field.Addr().Pointer())) = v
}
case reflect.Ptr:
valRv := reflect.ValueOf(value)
fieldType := field.Type().Elem()
valRvKind := valRv.Kind()
if valRvKind == reflect.Ptr {
valRvKind = valRv.Elem().Kind()
}
if fieldType.Kind() == reflect.Struct && valRvKind == reflect.Struct {
field.Set(valRv)
} else if field.Kind() == reflect.Slice && valRvKind == reflect.Slice {
field.Set(valRv)
} else if field.Kind() == reflect.Map && valRvKind == reflect.Map {
field.Set(valRv)
}
case reflect.Struct:
valRv := reflect.ValueOf(value)
field.Set(valRv)
case reflect.Slice:
valRv := reflect.ValueOf(value)
field.Set(valRv)
case reflect.Map:
valRv := reflect.ValueOf(value)
field.Set(valRv)
default:
}
}
}

View File

@ -21,10 +21,6 @@ type jsString struct {
V8Value
}
func (m *jsString) AsString() JSString {
return m
}
func (m *jsString) Value() string {
return m.value.String()
}