diff --git a/bridge/core/reflection.go b/bridge/core/reflection.go index b84aa2c..64d409c 100644 --- a/bridge/core/reflection.go +++ b/bridge/core/reflection.go @@ -3,6 +3,7 @@ package core import ( "fmt" "reflect" + "strconv" "sync" "github.com/grafana/sobek" @@ -337,6 +338,21 @@ func wrapJSCallback(vm *sobek.Runtime, callable sobek.Callable, goType reflect.T } func bindSlice(vm *sobek.Runtime, v reflect.Value, visited map[uintptr]sobek.Value) (sobek.Value, error) { + // @optimized: fast-path for []byte using ArrayBuffer + if v.Type().Elem() == reflect.TypeOf(byte(0)) { + var bytes []byte + if v.CanAddr() || v.Kind() == reflect.Slice { + bytes = v.Bytes() + } else { + l := v.Len() + bytes = make([]byte, l) + reflect.Copy(reflect.ValueOf(bytes), v) + } + copied := make([]byte, len(bytes)) + copy(copied, bytes) + return ToArrayBuffer(vm, copied), nil + } + // @optimized: Pre-allocate slice and use NewArray(vals...) to avoid repeated Set calls. l := v.Len() vals := make([]interface{}, l) @@ -352,16 +368,23 @@ func bindSlice(vm *sobek.Runtime, v reflect.Value, visited map[uintptr]sobek.Val func bindMap(vm *sobek.Runtime, v reflect.Value, visited map[uintptr]sobek.Value) (sobek.Value, error) { obj := vm.NewObject() - for _, key := range v.MapKeys() { + // @optimized: MapRange iteration and strconv fast paths for primitives + iter := v.MapRange() + for iter.Next() { + key := iter.Key() var keyStr string - // @optimized: Avoid Sprintf if key is already a string. - if key.Kind() == reflect.String { + switch key.Kind() { + case reflect.String: keyStr = key.String() - } else { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + keyStr = strconv.FormatInt(key.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + keyStr = strconv.FormatUint(key.Uint(), 10) + default: keyStr = fmt.Sprint(key.Interface()) } - val, err := bindValue(vm, v.MapIndex(key), visited) + val, err := bindValue(vm, iter.Value(), visited) if err != nil { return nil, err }