From c395ab46d67aaa0ea911d3878a286ea44a319175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E7=BA=A2=E5=B2=A9?= Date: Wed, 15 Mar 2023 14:29:45 +0800 Subject: [PATCH] upgrade-dev v2.3.7 --- cef/cef-application-callback.go | 2 + cef/cef-application.go | 2 +- cef/cef-events.go | 2 +- cef/cef-ipc-browser.go | 37 +++- cef/cef-ipc-render.go | 35 +++- cef/cef-ipc-value-convert.go | 42 ++++- cef/cef-ipc.go | 30 ++- example/dev-test/ipc-event/ipc-event.go | 17 +- .../ipc-event/resources/ipc-event.html | 37 +++- ipc/ipc-context.go | 6 +- ipc/ipc-invoke.go | 175 +++++++++--------- ipc/ipc-target.go | 2 + ipc/ipc.go | 96 ++++++---- 13 files changed, 325 insertions(+), 158 deletions(-) diff --git a/cef/cef-application-callback.go b/cef/cef-application-callback.go index 5bb0987c..ab90187e 100644 --- a/cef/cef-application-callback.go +++ b/cef/cef-application-callback.go @@ -44,6 +44,8 @@ func browserProcessMessageReceived(browser *ICefBrowser, frame *ICefFrame, sourc result = ipcBrowser.ipcGoExecuteMethodMessage(browser, frame, sourceProcess, message) } else if message.Name() == internalProcessMessageIPCOn { result = ipcBrowser.ipcOnMessage(browser, frame, sourceProcess, message) + } else if message.Name() == internalProcessMessageIPCEmitReply { + result = ipcBrowser.ipcGoExecuteMethodMessageReply(browser, frame, sourceProcess, message) } return } diff --git a/cef/cef-application.go b/cef/cef-application.go index 707c634b..3bcd86a2 100644 --- a/cef/cef-application.go +++ b/cef/cef-application.go @@ -359,7 +359,7 @@ func init() { if !*result { *result = renderProcessMessageReceived(browse, frame, processId, message) } - //frame.Free() + frame.Free() //browse.Free() message.Free() default: diff --git a/cef/cef-events.go b/cef/cef-events.go index c5cdd79f..92c448d1 100644 --- a/cef/cef-events.go +++ b/cef/cef-events.go @@ -86,7 +86,7 @@ func init() { if !*result { *result = browserProcessMessageReceived(browse, frame, processId, message) } - //frame.Free() + frame.Free() //browse.Free() message.Free() case ChromiumEventOnResourceLoadComplete: diff --git a/cef/cef-ipc-browser.go b/cef/cef-ipc-browser.go index 3b35c62f..74be2378 100644 --- a/cef/cef-ipc-browser.go +++ b/cef/cef-ipc-browser.go @@ -24,6 +24,41 @@ type ipcBrowserProcess struct { onHandler *ipcOnHandler // ipc.on handler } +func (m *ipcBrowserProcess) ipcGoExecuteMethodMessageReply(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) { + messageId := message.ArgumentList().GetInt(0) + if callback := ipc.CheckEmitCallback(messageId); callback != nil { + //第二个参数 true 有返回参数 + if isReturn := message.ArgumentList().GetBool(1); isReturn { + //[]byte + binaryValue := message.ArgumentList().GetBinary(2) + var ( + count uint32 + resultArgsBytes []byte + ) + if binaryValue.IsValid() { + size := binaryValue.GetSize() + resultArgsBytes = make([]byte, size) + count = binaryValue.GetData(resultArgsBytes, 0) + binaryValue.Free() + } + if count > 0 { + ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), false, resultArgsBytes) + if ctxCallback := callback.ContextCallback(); ctxCallback != nil { + ctxCallback.Invoke(ipcContext) + } else if argsCallback := callback.ArgumentCallback(); argsCallback != nil { + argsCallback.Invoke(ipcContext) + } + if ipcContext.ArgumentList() != nil { + ipcContext.ArgumentList().Free() + } + ipcContext.Result(nil) + } + resultArgsBytes = nil + } + } + return +} + // ipcGoExecuteMethodMessage 执行 Go 监听函数 func (m *ipcBrowserProcess) ipcGoExecuteMethodMessage(browser *ICefBrowser, frame *ICefFrame, sourceProcess consts.CefProcessId, message *ICefProcessMessage) (result bool) { result = true @@ -43,7 +78,7 @@ func (m *ipcBrowserProcess) ipcGoExecuteMethodMessage(browser *ICefBrowser, fram args.GetData(argsBytes, 0) args.Free() //立即释放掉 } - ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), argsBytes) + ipcContext := ipc.NewContext(browser.Identifier(), frame.Identifier(), true, argsBytes) argsBytes = nil //调用监听函数 if ctxCallback := eventCallback.ContextCallback(); ctxCallback != nil { diff --git a/cef/cef-ipc-render.go b/cef/cef-ipc-render.go index af040b35..007957cc 100644 --- a/cef/cef-ipc-render.go +++ b/cef/cef-ipc-render.go @@ -72,9 +72,9 @@ func (m *ipcRenderProcess) ipcJSOnEvent(name string, object *ICefV8Value, argume return } var ( - onName *ICefV8Value //事件名 + onName *ICefV8Value // 事件名 onNameValue string // 事件名 - onCallback *ICefV8Value //事件回调函数 + onCallback *ICefV8Value // 事件回调函数 ) onName = arguments.Get(0) //事件名 第一个参数必须是字符串 @@ -105,9 +105,12 @@ func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICef if callback := ipcRender.onHandler.getCallback(name); callback != nil { messageId := argument.GetInt(0) args := argument.GetBinary(2) - var argsBytes []byte - var count uint32 - var argsV8ValueArray *TCefV8ValueArray + var ( + argsBytes []byte + count uint32 + argsV8ValueArray *TCefV8ValueArray + resultData []byte + ) if args.IsValid() { size := args.GetSize() argsBytes = make([]byte, size) @@ -122,12 +125,25 @@ func (m *ipcRenderProcess) ipcGoExecuteJSEvent(browser *ICefBrowser, frame *ICef if argsV8ValueArray != nil { argsV8ValueArray.Free() } + if ret.IsUndefined() && ret.IsNull() { + resultData = ipcValueConvert.V8ValueToProcessMessageBytes(ret) + } ret.Free() callback.context.Exit() } argsBytes = nil if messageId != 0 { // callback - + replyMessage := ProcessMessageRef.new(internalProcessMessageIPCEmitReply) + replyMessage.ArgumentList().SetInt(0, messageId) + if resultData != nil { + replyMessage.ArgumentList().SetBool(1, true) //有返回值 + binaryValue := BinaryValueRef.New(resultData) + replyMessage.ArgumentList().SetBinary(2, binaryValue) //result []byte + } else { + replyMessage.ArgumentList().SetBool(1, false) //无返回值 + } + frame.SendProcessMessage(consts.PID_BROWSER, replyMessage) + replyMessage.Free() } result = true } @@ -246,8 +262,10 @@ func (m *ipcRenderProcess) ipcJSExecuteGoEventMessageReply(browser *ICefBrowser, if isReturn := message.ArgumentList().GetBool(1); isReturn { //[]byte binaryValue := message.ArgumentList().GetBinary(2) - var count uint32 - var resultArgsBytes []byte + var ( + count uint32 + resultArgsBytes []byte + ) if binaryValue.IsValid() { size := binaryValue.GetSize() resultArgsBytes = make([]byte, size) @@ -276,7 +294,6 @@ func (m *ipcRenderProcess) ipcJSExecuteGoEventMessageReply(browser *ICefBrowser, } //remove callback.free() - ipcRender.emitHandler.removeCallback(messageId) } return } diff --git a/cef/cef-ipc-value-convert.go b/cef/cef-ipc-value-convert.go index 83073479..a71b0454 100644 --- a/cef/cef-ipc-value-convert.go +++ b/cef/cef-ipc-value-convert.go @@ -252,9 +252,43 @@ func (m *v8ValueProcessMessageConvert) JSONObjectToV8Value(object json.JSONObjec return result } -// V8ValueToProcessMessageBytes ICefV8Value 转换 []byte 进程消息 +// V8ValueToProcessMessageBytes ICefV8Value 转换 [[]byte] 进程消息 func (m *v8ValueProcessMessageConvert) V8ValueToProcessMessageBytes(v8value *ICefV8Value) []byte { - if result, err := m.V8valueArrayToSlice(v8value); err == nil { + if v8value.IsArray() { + if result, err := m.V8valueArrayToSlice(v8value); err == nil { + if v, err := jsoniter.Marshal(result); err == nil { + return v + } + } + } else if v8value.IsObject() { + if result, err := m.V8valueObjectToMap(v8value); err == nil { + if v, err := jsoniter.Marshal(result); err == nil { + return v + } + } + } else { + result := make([]any, 1) + if v8value.IsString() { + result[0] = v8value.GetStringValue() + } else if v8value.IsInt() { + result[0] = int(v8value.GetIntValue()) + } else if v8value.IsUInt() { + result[0] = uint(v8value.GetUIntValue()) + } else if v8value.IsDouble() { + result[0] = v8value.GetDoubleValue() + } else if v8value.IsBool() { + result[0] = v8value.GetBoolValue() + } else if v8value.IsDate() { + result[0] = v8value.GetDateValue() + } else if v8value.IsNull() { + result[0] = "null" + } else if v8value.IsUndefined() { + result[0] = "undefined" + } else if v8value.IsArrayBuffer() { + result[0] = "" + } else { + result[0] = "" // function/byte/buffer + } if v, err := jsoniter.Marshal(result); err == nil { return v } @@ -281,6 +315,8 @@ func (m *v8ValueProcessMessageConvert) V8valueArrayToSlice(v8value *ICefV8Value) result[i] = args.GetDoubleValue() } else if args.IsBool() { result[i] = args.GetBoolValue() + } else if v8value.IsDate() { + result[i] = v8value.GetDateValue() } else if args.IsNull() { result[i] = "null" } else if args.IsUndefined() { @@ -327,6 +363,8 @@ func (m *v8ValueProcessMessageConvert) V8valueObjectToMap(v8value *ICefV8Value) result[key] = args.GetDoubleValue() } else if args.IsBool() { result[key] = args.GetBoolValue() + } else if v8value.IsDate() { + result[key] = v8value.GetDateValue() } else if args.IsNull() { result[key] = "null" } else if args.IsUndefined() { diff --git a/cef/cef-ipc.go b/cef/cef-ipc.go index a109f53e..38d129d1 100644 --- a/cef/cef-ipc.go +++ b/cef/cef-ipc.go @@ -16,14 +16,15 @@ import ( ) const ( - internalIPCKey = "ipc" // JavaScript -> ipc 事件驱动, 根对象名 - internalEmit = "emit" // JavaScript -> ipc.emit 在 JavaScript 触发 GO 监听事件函数名 - internalOn = "on" // JavaScript -> ipc.on 在 JavaScript 监听事件, 提供给 GO 调用 + internalIPCKey = "ipc" // JavaScript -> ipc 事件驱动, 根对象名 + internalEmit = "emit" // JavaScript -> ipc.emit 在 JavaScript 触发 GO 监听事件函数名, 异步 + internalEmitSync = "emitSync" // JavaScript -> ipc.emitSync 在 JavaScript 触发 GO 监听事件函数名, 同步 + internalOn = "on" // JavaScript -> ipc.on 在 JavaScript 监听事件, 提供给 GO 调用 ) const ( - internalProcessMessageIPCEmit = "emitHandler" // 进程消息 emitHandler - internalProcessMessageIPCEmitReply = "ipcEmitReply" // 进程消息 ipcEmitReply - internalProcessMessageIPCOn = "onHandler" // 进程消息 onHandler + internalProcessMessageIPCEmit = "emitHandler" // 进程消息 emit事件处理 + internalProcessMessageIPCEmitReply = "emitReply" // 进程消息 emit事件回复消息 + internalProcessMessageIPCOn = "onHandler" // 进程消息 on监听事件处理 ) var ( @@ -79,7 +80,8 @@ func ipcInit() { // isIPCInternalKey IPC 内部 key 不允许使用 func isIPCInternalKey(key string) bool { return key == internalIPCKey || key == internalEmit || key == internalOn || - key == internalProcessMessageIPCEmit || key == internalProcessMessageIPCOn || key == internalProcessMessageIPCEmitReply + key == internalProcessMessageIPCEmit || key == internalProcessMessageIPCOn || key == internalProcessMessageIPCEmitReply || + key == internalEmitSync } // addCallback @@ -96,20 +98,16 @@ func (m *ipcEmitHandler) addCallback(callback *ipcCallback) int32 { return m.callbackMessageId } -// removeCallback -func (m *ipcEmitHandler) removeCallback(messageId int32) { - //m.callbackList.Remove((*list.Element)(unsafe.Pointer(ptr))) - m.callbackLock.Lock() - defer m.callbackLock.Unlock() - delete(m.callbackList, messageId) -} - // getCallback func (m *ipcEmitHandler) getCallback(messageId int32) *ipcCallback { //return (*list.Element)(unsafe.Pointer(ptr)).Value.(*ipcCallback) m.callbackLock.Lock() defer m.callbackLock.Unlock() - return m.callbackList[messageId] + if callback, ok := m.callbackList[messageId]; ok { + delete(m.callbackList, messageId) + return callback + } + return nil } func (m *ipcEmitHandler) clear() { diff --git a/example/dev-test/ipc-event/ipc-event.go b/example/dev-test/ipc-event/ipc-event.go index ac6ce463..5f6f99a8 100644 --- a/example/dev-test/ipc-event/ipc-event.go +++ b/example/dev-test/ipc-event/ipc-event.go @@ -78,6 +78,8 @@ func main() { r10[2] = r9 var tm = time.Now().Second() var cha = 0 + + //监听事件,js触发,之后再触发js监听的事件 ipc.On("testGoEmit", func(context ipc.IContext) { count++ args := context.ArgumentList().JSONArray() @@ -90,27 +92,26 @@ func main() { cha = args.GetIntByIndex(0) tm = time.Now().Second() } - //触发JS监听的函数,并传入参数 + //触发JS监听的事件,并传入参数 ipc.Emit("onTestName1", r0, r1+count, r2, r3, r4, r5, r6, r7, r8, r9, r10) - //ipc.EmitAndCallback("", func() {}, "aaaa") }) - ipc.On("testGoEmitAndCallback", func(context ipc.IContext) { - fmt.Println("testGoEmit", context.BrowserId(), context.FrameId()) + ipc.On("testGoEmitAndCallback", func() { + fmt.Println("testGoEmitAndCallback") //触发JS监听的函数,并传入参数 - ipc.EmitAndCallback("onTestName1", []any{r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10}, func() { - + ipc.EmitAndCallback("onTestName2", []any{r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10}, func(r1 string) { + fmt.Println("onTestName2 r1: ", r1) }) //ipc.EmitAndCallback("", func() {}, "aaaa") }) - ipc.OnArguments("testResultArgs", func(args1 int) (string, int, float64, bool, *MyError, []string, []*src.StructVarDemo, []src.StructVarDemo, map[string]string, map[string]interface{}, []map[string]interface{}) { + ipc.On("testResultArgs", func(args1 int) (string, int, float64, bool, *MyError, []string, []*src.StructVarDemo, []src.StructVarDemo, map[string]string, map[string]interface{}, []map[string]interface{}) { fmt.Println("args1", args1) return r0, r1 + count, r2, r3, r4, r5, r6, r7, r8, r9, r10 }) - ipc.OnArguments("testInArgs", func(in1 string, in2 int, in3 float64, in4 bool, in5 []string, in6 []any, in7 map[string]any, in8 src.TestInArgs, in9 map[string]src.TestInArgs) (string, int, bool) { + ipc.On("testInArgs", func(in1 string, in2 int, in3 float64, in4 bool, in5 []string, in6 []any, in7 map[string]any, in8 src.TestInArgs, in9 map[string]src.TestInArgs) (string, int, bool) { fmt.Println("in1: ", in1) fmt.Println("in2: ", in2) fmt.Println("in3: ", in3) diff --git a/example/dev-test/ipc-event/resources/ipc-event.html b/example/dev-test/ipc-event/resources/ipc-event.html index 55c9d36b..c8a25b45 100644 --- a/example/dev-test/ipc-event/resources/ipc-event.html +++ b/example/dev-test/ipc-event/resources/ipc-event.html @@ -135,8 +135,10 @@ msg("R9:", r9, JSON.stringify(r9)); msg("R10:", r10, JSON.stringify(r10)); }); - ipc.on('onTestName2', function (param1, param2, param3) { - + ipc.on('onTestName2', function (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10) { + clearMsg() + msg("onTestName2"); + return ["返回值", 111111, 2222.22, true] }); let tgesi = null @@ -167,6 +169,34 @@ ipc.emit("testGoEmit", [idx]); } + + let tgesic = null + + function autotestGoEmitAndCallback() { + if (tgesic != null) { + clearInterval(tgesic) + tgesic = null + idx = 0; + return + } + tgesic = setInterval(testGoEmitAndCallback, 1) + if (tgesic != null) { + let time = document.getElementById("time").value - 0 + if (time > 0) { + setTimeout(function () { + clearInterval(tgesic) + msg(idx) + tgesic = null + idx = 0; + }, time) + } + } + } + function testGoEmitAndCallback() { + ipc.emit("testGoEmitAndCallback"); + } + + function bindFunc() { energy.funcName(); } @@ -196,6 +226,9 @@
+ + +

diff --git a/ipc/ipc-context.go b/ipc/ipc-context.go index 8723a08d..afe5a943 100644 --- a/ipc/ipc-context.go +++ b/ipc/ipc-context.go @@ -41,13 +41,15 @@ type Context struct { replay IReplay } -func NewContext(browserId int32, frameId int64, data []byte) IContext { +func NewContext(browserId int32, frameId int64, isReplay bool, data []byte) IContext { ctx := &Context{ browserId: browserId, frameId: frameId, - replay: &Replay{}, argument: json.NewJSONArray(data), } + if isReplay { + ctx.replay = new(Replay) + } data = nil return ctx } diff --git a/ipc/ipc-invoke.go b/ipc/ipc-invoke.go index 28ffe72a..6e382ca3 100644 --- a/ipc/ipc-invoke.go +++ b/ipc/ipc-invoke.go @@ -16,8 +16,6 @@ import ( "reflect" ) -var errorType = reflect.TypeOf((*error)(nil)).Elem() - // callback IPC 监听回调函数 type callback struct { context *contextCallback //上下文参数回调 @@ -26,7 +24,7 @@ type callback struct { // contextCallback 带上下文的回调函数 type contextCallback struct { - callback emitContextCallback + callback EmitContextCallback } // argumentCallback 带参数的回调函数 @@ -76,103 +74,110 @@ func (m *callback) ArgumentCallback() *argumentCallback { // Invoke 调用函数 func (m *argumentCallback) Invoke(context IContext) { - argsList := context.ArgumentList() - argsSize := argsList.Size() - rt := m.callback.Type() - inArgsCount := rt.NumIn() - var inArgsValues = make([]reflect.Value, inArgsCount) - for i := 0; i < inArgsCount; i++ { - inType := rt.In(i) - if i < argsSize { - argsValue := argsList.GetByIndex(i) - if argsValue == nil { - inArgsValues[i] = reflect.New(inType).Elem() - continue - } - 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() - continue - } - } + var ( + argsList json.JSONArray + argsSize int + inArgsValues []reflect.Value + ) + argsList = context.ArgumentList() + if argsList != nil { + argsSize = argsList.Size() + rt := m.callback.Type() + inArgsCount := rt.NumIn() + inArgsValues = make([]reflect.Value, inArgsCount) + for i := 0; i < inArgsCount; i++ { + inType := rt.In(i) + if i < argsSize { + argsValue := argsList.GetByIndex(i) + if argsValue == nil { + inArgsValues[i] = reflect.New(inType).Elem() + continue } - inArgsValues[i] = reflect.New(inType).Elem() - case reflect.Map: - if argsValue.IsObject() { - // map key=string : value != interface - if inType.Elem().Kind() != reflect.Interface { + 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 { - vv := reflect.New(inType) - if err := jsoniter.Unmarshal(jsonBytes, vv.Interface()); err == nil { - inArgsValues[i] = vv.Elem() + v := reflect.New(inType) + if err := jsoniter.Unmarshal(jsonBytes, v.Interface()); err == nil { + inArgsValues[i] = v.Elem() continue } } - inArgsValues[i] = reflect.New(inType).Elem() - } else { - inArgsValues[i] = reflect.ValueOf(argsValue.Data()) } - } else { inArgsValues[i] = reflect.New(inType).Elem() - } - case reflect.Slice: - if argsValue.IsArray() { - // slick 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() - continue + 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() + continue + } } + inArgsValues[i] = reflect.New(inType).Elem() + } else { + inArgsValues[i] = reflect.ValueOf(argsValue.Data()) } - inArgsValues[i] = reflect.New(inType).Elem() } else { - inArgsValues[i] = reflect.ValueOf(argsValue.Data()) + inArgsValues[i] = reflect.New(inType).Elem() } - } else { + case reflect.Slice: + if argsValue.IsArray() { + // slick 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() + continue + } + } + inArgsValues[i] = reflect.New(inType).Elem() + } else { + inArgsValues[i] = reflect.ValueOf(argsValue.Data()) + } + } else { + inArgsValues[i] = reflect.New(inType).Elem() + } + default: inArgsValues[i] = reflect.New(inType).Elem() } - default: + } else { inArgsValues[i] = reflect.New(inType).Elem() } - } else { - inArgsValues[i] = reflect.New(inType).Elem() } } // call diff --git a/ipc/ipc-target.go b/ipc/ipc-target.go index b6e6d301..faf44d91 100644 --- a/ipc/ipc-target.go +++ b/ipc/ipc-target.go @@ -12,6 +12,8 @@ package ipc // ITarget 指定目标 +// +// ipc.NewTarget() *Target type ITarget interface { GetBrowserId() int32 GetFrameId() int64 diff --git a/ipc/ipc.go b/ipc/ipc.go index c01f53e5..fe710831 100644 --- a/ipc/ipc.go +++ b/ipc/ipc.go @@ -24,16 +24,13 @@ var ( browser *browserIPC ) -// emitContextCallback IPC 上下文件回调函数 -type emitContextCallback func(context IContext) - -// emitArgumentCallback 带有参数回调函数 -type emitArgumentCallback any +// EmitContextCallback IPC 上下文件回调函数 +type EmitContextCallback func(context IContext) // browserIPC 主进程 IPC type browserIPC struct { onEvent map[string]*callback - emitCallback map[int32]*reflect.Value + emitCallback map[int32]*callback emitCallbackMessageId int32 onLock sync.Mutex emitLock sync.Mutex @@ -42,7 +39,21 @@ type browserIPC struct { func init() { if common.Args.IsMain() { - browser = &browserIPC{onEvent: make(map[string]*callback), emitCallback: make(map[int32]*reflect.Value)} + browser = &browserIPC{onEvent: make(map[string]*callback), emitCallback: make(map[int32]*callback)} + } +} + +func createCallback(fn any) *callback { + switch fn.(type) { + case func(context IContext): + return &callback{context: &contextCallback{callback: fn.(func(context IContext))}} + default: + v := reflect.ValueOf(fn) + // f must be a function + if v.Kind() != reflect.Func { + return nil + } + return &callback{argument: &argumentCallback{callback: &v}} } } @@ -54,12 +65,9 @@ func SetProcessMessage(pm IProcessMessage) { } //On -// IPC GO 监听事件, 上下文参数 -func On(name string, fn emitContextCallback) { - browser.addOnEvent(name, &callback{context: &contextCallback{callback: fn}}) -} - -//OnArguments +// +// 参数 回调函数fn: EmitContextCallback 或 func +// // IPC GO 监听事件, 自定义参数,仅支持对应 JavaScript 对应 Go 的常用类型 // // 入参 不限制个数 @@ -85,15 +93,10 @@ func On(name string, fn emitContextCallback) { // // 出参 // -// 与同入参相同 -func OnArguments(name string, fn emitArgumentCallback) { - if browser != nil { - v := reflect.ValueOf(fn) - // f must be a function - if v.Kind() != reflect.Func { - return - } - browser.addOnEvent(name, &callback{argument: &argumentCallback{callback: &v}}) +// 与入参相同 +func On(name string, fn any) { + if callbackFN := createCallback(fn); callbackFN != nil { + browser.addOnEvent(name, callbackFN) } } @@ -110,6 +113,12 @@ func RemoveOn(name string) { //Emit // IPC GO 中触发 JS 监听的事件 +// +// 参数 +// name: JS 监听的事件名 +// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string +// 复杂类型: slice, map, struct +// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{} func Emit(name string, argument ...any) { if browser == nil || name == "" || browser.processMessage == nil { return @@ -119,6 +128,13 @@ func Emit(name string, argument ...any) { //EmitAndCallback // IPC GO 中触发 JS 监听的事件 +// +// 参数 +// name: JS 监听的事件名 +// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string +// 复杂类型: slice, map, struct +// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{} +// callback: 无返回值的回调函数, 接收返回值. 函数类型 EmitContextCallback 或 func(...) {} func EmitAndCallback(name string, argument []any, callback any) { if browser == nil || name == "" || browser.processMessage == nil { return @@ -129,6 +145,13 @@ func EmitAndCallback(name string, argument []any, callback any) { //EmitTarget // IPC GO 中触发指定目标 JS 监听的事件 +// +// 参数 +// name: JS 监听的事件名 +// target: 接收事件的目标 +// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string +// 复杂类型: slice, map, struct +// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{} func EmitTarget(name string, target ITarget, argument ...any) { if browser == nil || name == "" || browser.processMessage == nil { return @@ -138,6 +161,14 @@ func EmitTarget(name string, target ITarget, argument ...any) { //EmitTargetAndCallback // IPC GO 中触发指定目标 JS 监听的事件 +// +// 参数 +// name: JS 监听的事件名 +// target: 接收事件的目标 +// []argument: 入参 基本类型: int(int8 ~ uint64), bool, float(float32、float64), string +// 复杂类型: slice, map, struct +// 复杂类型限制示例: slice: []interface{}, map: map[string]interface{} +// callback: 无返回值的回调函数, 接收返回值. 函数类型 EmitContextCallback 或 func(...) {} func EmitTargetAndCallback(name string, target ITarget, argument []any, callback any) { if browser == nil || name == "" || browser.processMessage == nil { return @@ -162,15 +193,15 @@ func CheckOnEvent(name string) *callback { //CheckEmitCallback // IPC 检查 GO Emit 回调函数是否存在,并返回回调函数 -func CheckEmitCallback(id int32) *reflect.Value { +func CheckEmitCallback(id int32) *callback { if browser == nil { return nil } browser.emitLock.Lock() defer browser.emitLock.Unlock() if fn, ok := browser.emitCallback[id]; ok { - delete(browser.emitCallback, id) //移除这个回调函数 - return fn //返回 + delete(browser.emitCallback, id) + return fn } return nil } @@ -206,11 +237,14 @@ func (m *browserIPC) addEmitCallback(fn any) int32 { } m.emitLock.Lock() defer m.emitLock.Unlock() - if m.emitCallbackMessageId == -1 { - m.emitCallbackMessageId = 1 - } else { - m.emitCallbackMessageId++ + if callbackFN := createCallback(fn); callbackFN != nil { + if m.emitCallbackMessageId == -1 { + m.emitCallbackMessageId = 1 + } else { + m.emitCallbackMessageId++ + } + m.emitCallback[m.emitCallbackMessageId] = callbackFN + return m.emitCallbackMessageId } - m.emitCallback[m.emitCallbackMessageId] = &rv - return m.emitCallbackMessageId + return 0 }