diff --git a/go.mod b/go.mod index 8e338921511..6dbc5893e54 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/grafana/xk6-output-prometheus-remote v0.4.0 github.com/grafana/xk6-redis v0.3.0 github.com/grafana/xk6-webcrypto v0.4.0 - github.com/grafana/xk6-websockets v0.6.0 + github.com/grafana/xk6-websockets v0.7.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc github.com/jhump/protoreflect v1.16.0 diff --git a/go.sum b/go.sum index 4b7c2a1dcef..f9292180ab7 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/grafana/xk6-redis v0.3.0 h1:eV1YO0miPqGFilN8sL/3OdO6Mm+hZH2nsvJm5dkE0 github.com/grafana/xk6-redis v0.3.0/go.mod h1:3e/U9i1Nm3WEaMy4nZSGMjVf8ZsFau+aXurYJhJ7MfQ= github.com/grafana/xk6-webcrypto v0.4.0 h1:CXRGkvVg8snYEyGCq3d5XGzDPxTPJ1m5CS68jPdtZZk= github.com/grafana/xk6-webcrypto v0.4.0/go.mod h1:+THllImZ8OWlsFc8llWqvzzjottlGdXq/7rIQ16zmFs= -github.com/grafana/xk6-websockets v0.6.0 h1:k1z8Xy4sGOB2+VF0q621MoNo0mYY12s8Cqqo5MMeO4w= -github.com/grafana/xk6-websockets v0.6.0/go.mod h1:D76ALTjp3bMugqx7ulseJ9TZrmSvDogieWxWXr8S0+A= +github.com/grafana/xk6-websockets v0.7.0 h1:oTdfQNISs3bEuALfPv9VvQgb3xOxbu3C/DBySf5DnOI= +github.com/grafana/xk6-websockets v0.7.0/go.mod h1:D76ALTjp3bMugqx7ulseJ9TZrmSvDogieWxWXr8S0+A= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= diff --git a/vendor/github.com/grafana/xk6-websockets/websockets/websockets.go b/vendor/github.com/grafana/xk6-websockets/websockets/websockets.go index 0fd751acd13..af24426b695 100644 --- a/vendor/github.com/grafana/xk6-websockets/websockets/websockets.go +++ b/vendor/github.com/grafana/xk6-websockets/websockets/websockets.go @@ -137,6 +137,7 @@ func (r *WebSocketsAPI) websocket(c sobek.ConstructorCall) *sobek.Object { obj: rt.NewObject(), tagsAndMeta: params.tagsAndMeta, sendPings: ping{timestamps: make(map[string]time.Time)}, + binaryType: blobBinaryType, } // Maybe have this after the goroutine below ?!? @@ -421,10 +422,6 @@ func (w *webSocket) loop() { } } -const binarytypeError = `websocket's binaryType hasn't been set to either "blob" or "arraybuffer", ` + - `but a binary message has been received. ` + - `"blob" is still not the default so the websocket is erroring out` - func (w *webSocket) queueMessage(msg *message) { w.tq.Queue(func() error { if w.readyState != OPEN { @@ -446,12 +443,7 @@ func (w *webSocket) queueMessage(msg *message) { if msg.mtype == websocket.BinaryMessage { var data any - // Lets error out for a k6 release, at least, when there's no binaryType set. - // In the future, we'll use "blob" as default, as per spec: - // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType switch w.binaryType { - case "": - return errors.New(binarytypeError) case blobBinaryType: var err error data, err = rt.New(w.blobConstructor, rt.ToValue([]interface{}{msg.data})) @@ -461,7 +453,7 @@ func (w *webSocket) queueMessage(msg *message) { case arraybufferBinaryType: data = rt.NewArrayBuffer(msg.data) default: - return fmt.Errorf(`unknown binaryType %s, the supported ones are "blob" and "arraybuffer"`, w.binaryType) + return fmt.Errorf(`unknown binaryType %q, the supported ones are "blob" and "arraybuffer"`, w.binaryType) } must(rt, ev.DefineDataProperty("data", rt.ToValue(data), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE)) } else { @@ -609,21 +601,9 @@ func (w *webSocket) send(msg sobek.Value) { t: time.Now(), } case *sobek.ArrayBuffer: - b := o.Bytes() - w.bufferedAmount += len(b) - w.writeQueueCh <- message{ - mtype: websocket.BinaryMessage, - data: b, - t: time.Now(), - } + w.sendArrayBuffer(*o) case sobek.ArrayBuffer: - b := o.Bytes() - w.bufferedAmount += len(b) - w.writeQueueCh <- message{ - mtype: websocket.BinaryMessage, - data: b, - t: time.Now(), - } + w.sendArrayBuffer(o) case map[string]interface{}: rt := w.vu.Runtime() obj := msg.ToObject(rt) @@ -638,10 +618,57 @@ func (w *webSocket) send(msg sobek.Value) { data: b, t: time.Now(), } - default: - common.Throw(w.vu.Runtime(), fmt.Errorf("unsupported send type %T", o)) + rt := w.vu.Runtime() + isView, err := isArrayBufferView(rt, msg) + if err != nil { + common.Throw(rt, + fmt.Errorf("got error while trying to check if argument is ArrayBufferView: %w", err)) + } + if !isView { + common.Throw(rt, fmt.Errorf("unsupported send type %T", o)) + } + + buffer := msg.ToObject(rt).Get("buffer") + ab, ok := buffer.Export().(sobek.ArrayBuffer) + if !ok { + common.Throw(rt, + fmt.Errorf("buffer of an ArrayBufferView was not an ArrayBuffer but %T", buffer.Export())) + } + w.sendArrayBuffer(ab) + } +} + +func (w *webSocket) sendArrayBuffer(o sobek.ArrayBuffer) { + b := o.Bytes() + w.bufferedAmount += len(b) + w.writeQueueCh <- message{ + mtype: websocket.BinaryMessage, + data: b, + t: time.Now(), + } +} + +func isArrayBufferView(rt *sobek.Runtime, v sobek.Value) (bool, error) { + var isView sobek.Callable + var ok bool + exc := rt.Try(func() { + isView, ok = sobek.AssertFunction( + rt.Get("ArrayBuffer").ToObject(rt).Get("isView")) + }) + if exc != nil { + return false, exc + } + + if !ok { + return false, fmt.Errorf("couldn't get ArrayBuffer.isView as it isn't a function") + } + + boolValue, err := isView(nil, v) + if err != nil { + return false, err } + return boolValue.ToBoolean(), nil } // Ping sends a ping message over the websocket. diff --git a/vendor/modules.txt b/vendor/modules.txt index 07fc3a6d6e2..9162d446b7c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -203,7 +203,7 @@ github.com/grafana/xk6-redis/redis # github.com/grafana/xk6-webcrypto v0.4.0 ## explicit; go 1.20 github.com/grafana/xk6-webcrypto/webcrypto -# github.com/grafana/xk6-websockets v0.6.0 +# github.com/grafana/xk6-websockets v0.7.0 ## explicit; go 1.20 github.com/grafana/xk6-websockets/websockets github.com/grafana/xk6-websockets/websockets/events