github.com/0chain/gosdk@v1.17.11/wasmsdk/jsbridge/output.go (about) 1 //go:build js && wasm 2 // +build js,wasm 3 4 package jsbridge 5 6 import ( 7 "reflect" 8 "syscall/js" 9 ) 10 11 // OutputBinder convert Outputs from js.Value to reflect.Value 12 type OutputBinder func([]reflect.Value) []js.Value 13 14 // OutputBuilder binder builder 15 type OutputBuilder struct { 16 fn reflect.Type 17 numOut int 18 binders []func(rv reflect.Value) js.Value 19 } 20 21 // NewOutputBuilder create OutputBuilder 22 func NewOutputBuilder(fn reflect.Type) *OutputBuilder { 23 return &OutputBuilder{ 24 fn: fn, 25 numOut: fn.NumOut(), 26 } 27 } 28 29 // Build build OutputBinder 30 // js.ValueOf returns x as a JavaScript value: 31 // 32 // | Go | JavaScript | 33 // | ---------------------- | ---------------------- | 34 // | js.Value | [its value] | 35 // | js.Func | function | 36 // | nil | null | 37 // | bool | boolean | 38 // | integers and floats | number | 39 // | string | string | 40 // | []interface{} | new array | 41 // | map[string]interface{} | new object | 42 // 43 // Panics if x is not one of the expected types. 44 func (b *OutputBuilder) Build() (OutputBinder, error) { 45 46 b.binders = make([]func(rv reflect.Value) js.Value, b.numOut) 47 48 for i := 0; i < b.numOut; i++ { 49 outputType := b.fn.Out(i) 50 51 // TODO: Fast path for basic types that do not require reflection. 52 switch outputType.String() { 53 case TypeError: 54 b.binders[i] = func(rv reflect.Value) js.Value { 55 if rv.IsNil() { 56 return js.Null() 57 } 58 59 err := rv.Interface().(error) 60 if err != nil { 61 jsErr := NewJsError(err.Error()) 62 return js.ValueOf(jsErr) 63 } 64 return js.Null() 65 66 } 67 case TypeBytes: 68 b.binders[i] = func(rv reflect.Value) js.Value { 69 if rv.IsNil() { 70 return js.Null() 71 } 72 73 buf := rv.Interface().([]byte) 74 75 return NewBytes(buf) 76 77 } 78 default: 79 b.binders[i] = func(rv reflect.Value) js.Value { 80 81 if rv.CanInterface() && rv.Interface() == nil { 82 return js.Null() 83 } 84 85 return NewObject(rv.Interface()) 86 } 87 } 88 } 89 90 return b.Bind, nil 91 } 92 93 // Bind bind js Outputs to reflect values 94 func (b *OutputBuilder) Bind(args []reflect.Value) []js.Value { 95 values := make([]js.Value, b.numOut) 96 for i := 0; i < b.numOut; i++ { 97 values[i] = b.binders[i](args[i]) 98 } 99 return values 100 }