From db3fb66ce04871068315784a137abc85d967202b Mon Sep 17 00:00:00 2001 From: Mihail Stoykov Date: Thu, 6 Jun 2024 12:30:54 +0300 Subject: [PATCH] Switch to our fork of goja - sobek This is part of #3772 and #3773. Moving to the currently only aliases codebase lets us update dependent modules such as extension one at a time. --- go.mod | 3 +- go.sum | 27 +--- js/bundle.go | 36 ++--- js/bundle_test.go | 14 +- js/common/bridge.go | 6 +- js/common/frozen_object.go | 24 ++-- js/common/frozen_object_test.go | 4 +- js/common/interrupt_error.go | 6 +- js/common/randsource.go | 4 +- js/common/tags.go | 10 +- js/common/util.go | 20 +-- js/common/util_test.go | 16 +-- js/compiler/compiler.go | 34 ++--- js/compiler/compiler_test.go | 24 ++-- js/compiler/enhanced_test.go | 4 +- js/console.go | 16 +-- js/console_test.go | 8 +- js/eventloop/eventloop.go | 18 +-- js/eventloop/eventloop_test.go | 24 ++-- js/initcontext.go | 4 +- js/initcontext_test.go | 42 +++--- js/modules/cjsmodule.go | 10 +- js/modules/gomodule.go | 10 +- js/modules/k6/crypto/crypto.go | 8 +- js/modules/k6/crypto/crypto_test.go | 14 +- js/modules/k6/crypto/x509/x509_test.go | 6 +- js/modules/k6/data/data.go | 18 +-- js/modules/k6/data/share.go | 34 ++--- js/modules/k6/data/share_test.go | 12 +- js/modules/k6/encoding/encoding_test.go | 6 +- js/modules/k6/execution/execution.go | 64 ++++----- js/modules/k6/execution/execution_test.go | 20 +-- js/modules/k6/experimental/experimental.go | 6 +- js/modules/k6/experimental/fs/module.go | 18 +-- js/modules/k6/experimental/streams/errors.go | 26 ++-- js/modules/k6/experimental/streams/goja.go | 40 +++--- js/modules/k6/experimental/streams/module.go | 44 +++--- js/modules/k6/experimental/streams/queue.go | 14 +- .../streams/readable_stream_controller.go | 16 +-- .../readable_stream_default_controller.go | 34 ++--- .../streams/readable_stream_default_reader.go | 22 +-- .../streams/readable_stream_reader.go | 38 +++--- .../experimental/streams/readable_streams.go | 83 ++++++------ .../experimental/streams/underlying_source.go | 20 +-- js/modules/k6/experimental/tracing/client.go | 46 +++---- .../k6/experimental/tracing/client_test.go | 24 ++-- js/modules/k6/experimental/tracing/module.go | 10 +- js/modules/k6/experimental/tracing/options.go | 6 +- js/modules/k6/grpc/client.go | 18 +-- js/modules/k6/grpc/grpc.go | 10 +- js/modules/k6/grpc/helpers_test.go | 4 +- js/modules/k6/grpc/listeners.go | 14 +- js/modules/k6/grpc/params.go | 8 +- js/modules/k6/grpc/params_test.go | 4 +- js/modules/k6/grpc/stream.go | 20 +-- js/modules/k6/grpc/stream_test.go | 4 +- js/modules/k6/grpc/teststate_test.go | 6 +- js/modules/k6/html/element.go | 88 ++++++------ js/modules/k6/html/element_test.go | 12 +- js/modules/k6/html/elements.go | 104 +++++++------- js/modules/k6/html/elements_gen.go | 24 ++-- js/modules/k6/html/elements_test.go | 70 +++++----- js/modules/k6/html/gen/gen_elements.go | 18 +-- js/modules/k6/html/html.go | 68 +++++----- js/modules/k6/html/html_test.go | 22 +-- js/modules/k6/html/serialize.go | 8 +- js/modules/k6/html/serialize_test.go | 4 +- js/modules/k6/html/util.go | 14 +- js/modules/k6/http/cookiejar.go | 6 +- js/modules/k6/http/file_test.go | 18 +-- js/modules/k6/http/http.go | 18 +-- js/modules/k6/http/request.go | 40 +++--- js/modules/k6/http/response.go | 30 ++-- js/modules/k6/http/response_callback.go | 14 +- js/modules/k6/http/response_callback_test.go | 4 +- js/modules/k6/k6.go | 22 +-- js/modules/k6/metrics/metrics.go | 20 +-- js/modules/k6/metrics/metrics_test.go | 10 +- js/modules/k6/timers/timers.go | 10 +- js/modules/k6/ws/ws.go | 58 ++++---- js/modules/modules.go | 6 +- js/modules/require_impl.go | 12 +- js/modules/resolution.go | 12 +- js/modules_vu.go | 6 +- js/modulestest/compile.go | 12 +- js/modulestest/modulestest.go | 6 +- js/modulestest/runtime.go | 6 +- js/promises/promises.go | 6 +- js/runner.go | 54 ++++---- js/summary.go | 8 +- js/tc39/tc39_test.go | 50 +++---- vendor/github.com/dop251/goja/README.md | 2 +- vendor/github.com/dop251/goja/compiler.go | 41 ++++-- .../github.com/dop251/goja/compiler_expr.go | 26 ++-- vendor/github.com/dop251/goja/vm.go | 6 +- vendor/github.com/grafana/sobek/LICENSE | 15 ++ vendor/github.com/grafana/sobek/README.md | 7 + vendor/github.com/grafana/sobek/aliases.go | 128 ++++++++++++++++++ vendor/modules.txt | 7 +- 99 files changed, 1162 insertions(+), 1011 deletions(-) create mode 100644 vendor/github.com/grafana/sobek/LICENSE create mode 100644 vendor/github.com/grafana/sobek/README.md create mode 100644 vendor/github.com/grafana/sobek/aliases.go diff --git a/go.mod b/go.mod index 2f6bc07f28c..52461810e92 100644 --- a/go.mod +++ b/go.mod @@ -8,12 +8,13 @@ require ( github.com/PuerkitoBio/goquery v1.9.1 github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5 github.com/andybalholm/brotli v1.1.0 - github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 + github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2 github.com/evanw/esbuild v0.21.2 github.com/fatih/color v1.16.0 github.com/go-sourcemap/sourcemap v2.1.4+incompatible github.com/golang/protobuf v1.5.4 github.com/gorilla/websocket v1.5.1 + github.com/grafana/sobek v0.0.0-20240606091932-2da0e9e5f3e7 github.com/grafana/xk6-browser v1.5.1 github.com/grafana/xk6-dashboard v0.7.3 github.com/grafana/xk6-output-prometheus-remote v0.3.1 diff --git a/go.sum b/go.sum index 263a203a68f..d05de21245e 100644 --- a/go.sum +++ b/go.sum @@ -32,27 +32,18 @@ github.com/chromedp/cdproto v0.0.0-20221023212508-67ada9507fb2 h1:xESwMZNYkDnZf9 github.com/chromedp/cdproto v0.0.0-20221023212508-67ada9507fb2/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.9.0 h1:pTK/l/3qYIKaRXuHnEnIf7Y5NxfRPfpb7dis6/gdlVI= github.com/dlclark/regexp2 v1.9.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM= -github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2 h1:OFTHt+yJDo/uaIKMGjEKzc3DGhrpQZoqvMUIloZv6ZY= +github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2/go.mod h1:o31y53rb/qiIAONF7w3FHJZRqqP3fzHUr1HqanthByw= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -70,7 +61,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -87,13 +77,14 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230728192033-2ba5b33183c6 h1:ZgoomqkdjGbQ3+qQXCkvYMCDvGDNg2k5JJDjjdTB6jY= github.com/google/pprof v0.0.0-20230728192033-2ba5b33183c6/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grafana/sobek v0.0.0-20240606091932-2da0e9e5f3e7 h1:Ed0df3dkkPsjL0RKagJAv/821vrTBiB6GBk+198pxi4= +github.com/grafana/sobek v0.0.0-20240606091932-2da0e9e5f3e7/go.mod h1:6ZH0b0iOxyigeTh+/IlGoL0Hd3lVXA94xoXf0ldNgCM= github.com/grafana/xk6-browser v1.5.1 h1:wexnBtx1raDniYcXkRQ9zfXvuJGjvixZag4kmiYG3tg= github.com/grafana/xk6-browser v1.5.1/go.mod h1:hD9H1zpe1Fvs6RCENKnaPqpObh6alz+hX00Xf5qvDE4= github.com/grafana/xk6-dashboard v0.7.3 h1:47dxL87eMhpCIHSJTOnohTq3WIfCwvNriRTDvYNlsHY= @@ -110,7 +101,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20190402204710-8ff2fc3824fc h1:KpMgaYJRieDkHZJWY3LMafvtqS/U8xX6+lUN+OKpl/Y= @@ -125,13 +115,10 @@ github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLA github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -173,7 +160,6 @@ github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0= github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I= github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e h1:zWKUYT07mGmVBH+9UgnHXd/ekCK99C8EbDSAt5qsjXE= @@ -279,7 +265,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -298,9 +283,7 @@ golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -348,8 +331,6 @@ gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UD gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/guregu/null.v3 v3.3.0 h1:8j3ggqq+NgKt/O7mbFVUFKUMWN+l1AmT5jQmJ6nPh2c= gopkg.in/guregu/null.v3 v3.3.0/go.mod h1:E4tX2Qe3h7QdL+uZ3a0vqvYwKQsRSQKM5V4YltdgH9Y= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/js/bundle.go b/js/bundle.go index 481b24f4180..b6cd546cd04 100644 --- a/js/bundle.go +++ b/js/bundle.go @@ -10,7 +10,7 @@ import ( "path/filepath" "runtime" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "gopkg.in/guregu/null.v3" @@ -43,22 +43,22 @@ type Bundle struct { // A BundleInstance is a self-contained instance of a Bundle. type BundleInstance struct { - Runtime *goja.Runtime + Runtime *sobek.Runtime // TODO: maybe just have a reference to the Bundle? or save and pass rtOpts? env map[string]string - mainModuleExports *goja.Object + mainModuleExports *sobek.Object moduleVUImpl *moduleVUImpl } -func (bi *BundleInstance) getCallableExport(name string) goja.Callable { - fn, ok := goja.AssertFunction(bi.getExported(name)) +func (bi *BundleInstance) getCallableExport(name string) sobek.Callable { + fn, ok := sobek.AssertFunction(bi.getExported(name)) _ = ok // TODO maybe return it return fn } -func (bi *BundleInstance) getExported(name string) goja.Value { +func (bi *BundleInstance) getExported(name string) sobek.Value { return bi.mainModuleExports.Get(name) } @@ -101,7 +101,7 @@ func newBundle( // TODO use a real context vuImpl := &moduleVUImpl{ ctx: context.Background(), - runtime: goja.New(), + runtime: sobek.New(), events: events{ global: piState.Events, local: event.NewEventSystem(100, piState.Logger), @@ -171,10 +171,10 @@ func (b *Bundle) makeArchive() *lib.Archive { } // populateExports validates and extracts exported objects -func (b *Bundle) populateExports(updateOptions bool, exports *goja.Object) error { +func (b *Bundle) populateExports(updateOptions bool, exports *sobek.Object) error { for _, k := range exports.Keys() { v := exports.Get(k) - if _, ok := goja.AssertFunction(v); ok && k != consts.Options { + if _, ok := sobek.AssertFunction(v); ok && k != consts.Options { b.callableExports[k] = struct{}{} continue } @@ -215,7 +215,7 @@ func (b *Bundle) Instantiate(ctx context.Context, vuID uint64) (*BundleInstance, // runtime, but no state, to allow module-provided types to function within the init context. vuImpl := &moduleVUImpl{ ctx: ctx, - runtime: goja.New(), + runtime: sobek.New(), events: events{ global: b.preInitState.Events, local: event.NewEventSystem(100, b.preInitState.Logger), @@ -237,7 +237,7 @@ func (b *Bundle) Instantiate(ctx context.Context, vuID uint64) (*BundleInstance, // Grab any exported functions that could be executed. These were // already pre-validated in cmd.validateScenarioConfig(), just get them here. jsOptions := exports.Get(consts.Options) - var jsOptionsObj *goja.Object + var jsOptionsObj *sobek.Object if common.IsNullish(jsOptions) { jsOptionsObj = vuImpl.runtime.NewObject() err := exports.Set(consts.Options, jsOptionsObj) @@ -268,7 +268,7 @@ func (b *Bundle) newCompiler(logger logrus.FieldLogger) *compiler.Compiler { return c } -func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, error) { +func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*sobek.Object, error) { rt := vuImpl.runtime err := b.setupJSRuntime(rt, int64(vuID), b.preInitState.Logger) if err != nil { @@ -301,7 +301,7 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e close(initDone) }() - var exportsV goja.Value + var exportsV sobek.Value err = common.RunWithPanicCatching(b.preInitState.Logger, rt, func() error { return vuImpl.eventLoop.Start(func() error { var err error @@ -313,7 +313,7 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e <-initDone if err != nil { - var exception *goja.Exception + var exception *sobek.Exception if errors.As(err, &exception) { err = &scriptExceptionError{inner: exception} } @@ -339,7 +339,7 @@ func (b *Bundle) instantiate(vuImpl *moduleVUImpl, vuID uint64) (*goja.Object, e return exports, nil } -func (b *Bundle) setupJSRuntime(rt *goja.Runtime, vuID int64, logger logrus.FieldLogger) error { +func (b *Bundle) setupJSRuntime(rt *sobek.Runtime, vuID int64, logger logrus.FieldLogger) error { rt.SetFieldNameMapper(common.FieldNameMapper{}) rt.SetRandSource(common.NewRandSource()) @@ -375,14 +375,14 @@ type requireImpl struct { internal *modules.LegacyRequireImpl } -func (r *requireImpl) require(specifier string) (*goja.Object, error) { +func (r *requireImpl) require(specifier string) (*sobek.Object, error) { if !r.inInitContext() { return nil, fmt.Errorf(cantBeUsedOutsideInitContextMsg, "require") } return r.internal.Require(specifier) } -func (b *Bundle) setInitGlobals(rt *goja.Runtime, vu *moduleVUImpl, modSys *modules.ModuleSystem) { +func (b *Bundle) setInitGlobals(rt *sobek.Runtime, vu *moduleVUImpl, modSys *modules.ModuleSystem) { mustSet := func(k string, v interface{}) { if err := rt.Set(k, v); err != nil { panic(fmt.Errorf("failed to set '%s' global object: %w", k, err)) @@ -396,7 +396,7 @@ func (b *Bundle) setInitGlobals(rt *goja.Runtime, vu *moduleVUImpl, modSys *modu mustSet("require", impl.require) - mustSet("open", func(filename string, args ...string) (goja.Value, error) { + mustSet("open", func(filename string, args ...string) (sobek.Value, error) { // TODO fix in stack traces if vu.state != nil { return nil, fmt.Errorf(cantBeUsedOutsideInitContextMsg, "open") diff --git a/js/bundle_test.go b/js/bundle_test.go index 6bdc191443a..90620325a62 100644 --- a/js/bundle_test.go +++ b/js/bundle_test.go @@ -13,7 +13,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -480,7 +480,7 @@ func TestNewBundleFromArchive(t *testing.T) { require.Equal(t, lib.Options{VUs: null.IntFrom(12345)}, b.Options) bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - val, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + val, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.Equal(t, "hi!", val.Export()) } @@ -573,7 +573,7 @@ func TestNewBundleFromArchive(t *testing.T) { require.NoError(t, err) bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - val, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + val, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.Equal(t, int64(999), val.Export()) }) @@ -719,7 +719,7 @@ func TestOpen(t *testing.T) { t.Run(source, func(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - v, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + v, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.Equal(t, "hi", v.Export()) }) @@ -754,7 +754,7 @@ func TestBundleInstantiate(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - v, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + v, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.Equal(t, true, v.Export()) }) @@ -821,7 +821,7 @@ func TestBundleEnv(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) }) } @@ -859,7 +859,7 @@ func TestBundleNotSharable(t *testing.T) { require.NoError(t, err) for j := 0; j < iters; j++ { require.NoError(t, bi.Runtime.Set("__ITER", j)) - _, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) } } diff --git a/js/common/bridge.go b/js/common/bridge.go index aefbced9023..5535ed161fd 100644 --- a/js/common/bridge.go +++ b/js/common/bridge.go @@ -67,15 +67,15 @@ func MethodName(_ reflect.Type, m reflect.Method) string { return strings.ToLower(m.Name[0:1]) + m.Name[1:] } -// FieldNameMapper for goja.Runtime.SetFieldNameMapper() +// FieldNameMapper for sobek.Runtime.SetFieldNameMapper() type FieldNameMapper struct{} -// FieldName is part of the goja.FieldNameMapper interface +// FieldName is part of the sobek.FieldNameMapper interface // https://godoc.org/github.com/dop251/goja#FieldNameMapper func (FieldNameMapper) FieldName(t reflect.Type, f reflect.StructField) string { return FieldName(t, f) } -// MethodName is part of the goja.FieldNameMapper interface +// MethodName is part of the sobek.FieldNameMapper interface // https://godoc.org/github.com/dop251/goja#FieldNameMapper func (FieldNameMapper) MethodName(t reflect.Type, m reflect.Method) string { return MethodName(t, m) } diff --git a/js/common/frozen_object.go b/js/common/frozen_object.go index 9f0c872a6a5..5f596dbf651 100644 --- a/js/common/frozen_object.go +++ b/js/common/frozen_object.go @@ -3,17 +3,17 @@ package common import ( "fmt" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) // FreezeObject replicates the JavaScript Object.freeze function. -func FreezeObject(rt *goja.Runtime, obj goja.Value) error { +func FreezeObject(rt *sobek.Runtime, obj sobek.Value) error { global := rt.GlobalObject().Get("Object").ToObject(rt) - freeze, ok := goja.AssertFunction(global.Get("freeze")) + freeze, ok := sobek.AssertFunction(global.Get("freeze")) if !ok { panic("failed to get the Object.freeze function from the runtime") } - isFrozen, ok := goja.AssertFunction(global.Get("isFrozen")) + isFrozen, ok := sobek.AssertFunction(global.Get("isFrozen")) if !ok { panic("failed to get the Object.isFrozen function from the runtime") } @@ -27,18 +27,18 @@ func FreezeObject(rt *goja.Runtime, obj goja.Value) error { } type freezing struct { - rt *goja.Runtime - global goja.Value - freeze goja.Callable - isFrozen goja.Callable + rt *sobek.Runtime + global sobek.Value + freeze sobek.Callable + isFrozen sobek.Callable } -func (f *freezing) deepFreeze(val goja.Value) error { - if val != nil && goja.IsNull(val) { +func (f *freezing) deepFreeze(val sobek.Value) error { + if val != nil && sobek.IsNull(val) { return nil } - _, err := f.freeze(goja.Undefined(), val) + _, err := f.freeze(sobek.Undefined(), val) if err != nil { return fmt.Errorf("object freeze failed: %w", err) } @@ -53,7 +53,7 @@ func (f *freezing) deepFreeze(val goja.Value) error { if prop == nil { continue } - frozen, err := f.isFrozen(goja.Undefined(), prop) + frozen, err := f.isFrozen(sobek.Undefined(), prop) if err != nil { return err } diff --git a/js/common/frozen_object_test.go b/js/common/frozen_object_test.go index 9269b7d711a..afe6752f42a 100644 --- a/js/common/frozen_object_test.go +++ b/js/common/frozen_object_test.go @@ -3,7 +3,7 @@ package common import ( "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -11,7 +11,7 @@ import ( func TestFrozenObject(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() obj := rt.NewObject() require.NoError(t, obj.Set("foo", "bar")) require.NoError(t, rt.Set("obj", obj)) diff --git a/js/common/interrupt_error.go b/js/common/interrupt_error.go index 3270cd8f01f..0ed89f3239d 100644 --- a/js/common/interrupt_error.go +++ b/js/common/interrupt_error.go @@ -3,12 +3,12 @@ package common import ( "errors" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) -// UnwrapGojaInterruptedError returns the internal error handled by goja. +// UnwrapGojaInterruptedError returns the internal error handled by sobek. func UnwrapGojaInterruptedError(err error) error { - var gojaErr *goja.InterruptedError + var gojaErr *sobek.InterruptedError if errors.As(err, &gojaErr) { if e, ok := gojaErr.Value().(error); ok { return e diff --git a/js/common/randsource.go b/js/common/randsource.go index 489c0775fb8..141e547071a 100644 --- a/js/common/randsource.go +++ b/js/common/randsource.go @@ -6,14 +6,14 @@ import ( "fmt" "math/rand" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) // NewRandSource is copied from goja's source code: // https://github.com/dop251/goja/blob/master/goja/main.go#L44 // The returned RandSource is NOT safe for concurrent use: // https://golang.org/pkg/math/rand/#NewSource -func NewRandSource() goja.RandSource { +func NewRandSource() sobek.RandSource { var seed int64 if err := binary.Read(crand.Reader, binary.LittleEndian, &seed); err != nil { panic(fmt.Errorf("could not read random bytes: %w", err)) diff --git a/js/common/tags.go b/js/common/tags.go index 9b367f7c662..a431ec8d527 100644 --- a/js/common/tags.go +++ b/js/common/tags.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/metrics" ) @@ -12,8 +12,8 @@ import ( // user specified custom tags and metadata. // It expects to receive the `keyValues` object in the `{key1: value1, key2: // value2, ...}` format. -func ApplyCustomUserTags(rt *goja.Runtime, tagsAndMeta *metrics.TagsAndMeta, keyValues goja.Value) error { - if keyValues == nil || goja.IsNull(keyValues) || goja.IsUndefined(keyValues) { +func ApplyCustomUserTags(rt *sobek.Runtime, tagsAndMeta *metrics.TagsAndMeta, keyValues sobek.Value) error { + if keyValues == nil || sobek.IsNull(keyValues) || sobek.IsUndefined(keyValues) { return nil } @@ -30,7 +30,7 @@ func ApplyCustomUserTags(rt *goja.Runtime, tagsAndMeta *metrics.TagsAndMeta, key // ApplyCustomUserTag modifies the given metrics.TagsAndMeta object with the // given custom tag and theirs value. -func ApplyCustomUserTag(tagsAndMeta *metrics.TagsAndMeta, key string, val goja.Value) error { +func ApplyCustomUserTag(tagsAndMeta *metrics.TagsAndMeta, key string, val sobek.Value) error { kind := reflect.Invalid if typ := val.ExportType(); typ != nil { kind = typ.Kind() @@ -57,7 +57,7 @@ func ApplyCustomUserTag(tagsAndMeta *metrics.TagsAndMeta, key string, val goja.V // ApplyCustomUserMetadata modifies the given metrics.TagsAndMeta object with the // given custom metadata and their value. -func ApplyCustomUserMetadata(tagsAndMeta *metrics.TagsAndMeta, key string, val goja.Value) error { +func ApplyCustomUserMetadata(tagsAndMeta *metrics.TagsAndMeta, key string, val sobek.Value) error { kind := reflect.Invalid if typ := val.ExportType(); typ != nil { kind = typ.Kind() diff --git a/js/common/util.go b/js/common/util.go index 90b95e7cadd..868527a9416 100644 --- a/js/common/util.go +++ b/js/common/util.go @@ -7,14 +7,14 @@ import ( "io" "runtime/debug" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "go.k6.io/k6/errext" ) // Throw a JS error; avoids re-wrapping GoErrors. -func Throw(rt *goja.Runtime, err error) { - if e, ok := err.(*goja.Exception); ok { //nolint:errorlint // we don't really want to unwrap here +func Throw(rt *sobek.Runtime, err error) { + if e, ok := err.(*sobek.Exception); ok { //nolint:errorlint // we don't really want to unwrap here panic(e) } panic(rt.NewGoError(err)) // this catches the stack unlike rt.ToValue @@ -29,7 +29,7 @@ func GetReader(data interface{}) (io.Reader, error) { return bytes.NewBuffer(r), nil case io.Reader: return r, nil - case goja.ArrayBuffer: + case sobek.ArrayBuffer: return bytes.NewBuffer(r.Bytes()), nil default: return nil, fmt.Errorf("invalid type %T, it needs to be a string or ArrayBuffer", data) @@ -43,7 +43,7 @@ func ToBytes(data interface{}) ([]byte, error) { return dt, nil case string: return []byte(dt), nil - case goja.ArrayBuffer: + case sobek.ArrayBuffer: return dt.Bytes(), nil default: return nil, fmt.Errorf("invalid type %T, expected string, []byte or ArrayBuffer", data) @@ -57,7 +57,7 @@ func ToString(data interface{}) (string, error) { return string(dt), nil case string: return dt, nil - case goja.ArrayBuffer: + case sobek.ArrayBuffer: return string(dt.Bytes()), nil default: return "", fmt.Errorf("invalid type %T, expected string, []byte or ArrayBuffer", data) @@ -65,7 +65,7 @@ func ToString(data interface{}) (string, error) { } // RunWithPanicCatching catches panic and converts into an InterruptError error that should abort a script -func RunWithPanicCatching(logger logrus.FieldLogger, _ *goja.Runtime, fn func() error) (err error) { +func RunWithPanicCatching(logger logrus.FieldLogger, _ *sobek.Runtime, fn func() error) (err error) { defer func() { if r := recover(); r != nil { err = &errext.InterruptError{Reason: fmt.Sprintf("a panic occurred during JS execution: %s", r)} @@ -81,12 +81,12 @@ func RunWithPanicCatching(logger logrus.FieldLogger, _ *goja.Runtime, fn func() } // IsNullish checks if the given value is nullish, i.e. nil, undefined or null. -func IsNullish(v goja.Value) bool { - return v == nil || goja.IsUndefined(v) || goja.IsNull(v) +func IsNullish(v sobek.Value) bool { + return v == nil || sobek.IsUndefined(v) || sobek.IsNull(v) } // IsAsyncFunction checks if the provided value is an AsyncFunction -func IsAsyncFunction(rt *goja.Runtime, val goja.Value) bool { +func IsAsyncFunction(rt *sobek.Runtime, val sobek.Value) bool { if IsNullish(val) { return false } diff --git a/js/common/util_test.go b/js/common/util_test.go index cf81235b384..38345d430cb 100644 --- a/js/common/util_test.go +++ b/js/common/util_test.go @@ -5,28 +5,28 @@ import ( "fmt" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestThrow(t *testing.T) { t.Parallel() - rt := goja.New() - fn1, ok := goja.AssertFunction(rt.ToValue(func() { Throw(rt, errors.New("aaaa")) })) + rt := sobek.New() + fn1, ok := sobek.AssertFunction(rt.ToValue(func() { Throw(rt, errors.New("aaaa")) })) require.True(t, ok, "fn1 is invalid") - _, err := fn1(goja.Undefined()) + _, err := fn1(sobek.Undefined()) assert.EqualError(t, err, "GoError: aaaa") - fn2, ok := goja.AssertFunction(rt.ToValue(func() { Throw(rt, err) })) + fn2, ok := sobek.AssertFunction(rt.ToValue(func() { Throw(rt, err) })) require.True(t, ok, "fn2 is invalid") - _, err = fn2(goja.Undefined()) + _, err = fn2(sobek.Undefined()) assert.EqualError(t, err, "GoError: aaaa") } func TestToBytes(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() b := []byte("hello") testCases := []struct { in interface{} @@ -55,7 +55,7 @@ func TestToBytes(t *testing.T) { func TestToString(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() s := "hello" testCases := []struct { in interface{} diff --git a/js/compiler/compiler.go b/js/compiler/compiler.go index be336fff57e..f0f9d7acc11 100644 --- a/js/compiler/compiler.go +++ b/js/compiler/compiler.go @@ -14,9 +14,9 @@ import ( "sync" "time" - "github.com/dop251/goja" "github.com/dop251/goja/parser" "github.com/go-sourcemap/sourcemap" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "go.k6.io/k6/lib" @@ -72,11 +72,11 @@ var ( maxSrcLenForBabelSourceMap = 250 * 1024 //nolint:gochecknoglobals maxSrcLenForBabelSourceMapOnce sync.Once //nolint:gochecknoglobals - onceBabelCode sync.Once //nolint:gochecknoglobals - globalBabelCode *goja.Program //nolint:gochecknoglobals - errGlobalBabelCode error //nolint:gochecknoglobals - onceBabel sync.Once //nolint:gochecknoglobals - globalBabel *babel //nolint:gochecknoglobals + onceBabelCode sync.Once //nolint:gochecknoglobals + globalBabelCode *sobek.Program //nolint:gochecknoglobals + errGlobalBabelCode error //nolint:gochecknoglobals + onceBabel sync.Once //nolint:gochecknoglobals + globalBabel *babel //nolint:gochecknoglobals ) const ( @@ -84,7 +84,7 @@ const ( sourceMapURLFromBabel = "k6://internal-should-not-leak/file.map" ) -// A Compiler compiles JavaScript source code (ES5.1 or ES6) into a goja.Program +// A Compiler compiles JavaScript source code (ES5.1 or ES6) into a sobek.Program type Compiler struct { logger logrus.FieldLogger babel *babel @@ -173,7 +173,7 @@ type compilationState struct { // Compile the program in the given CompatibilityMode, wrapping it between pre and post code // TODO isESM will be used once goja support ESM modules natively -func (c *Compiler) Compile(src, filename string, isESM bool) (*goja.Program, string, error) { +func (c *Compiler) Compile(src, filename string, isESM bool) (*sobek.Program, string, error) { return c.compileImpl(src, filename, !isESM, c.Options.CompatibilityMode, nil) } @@ -206,7 +206,7 @@ func (c *compilationState) sourceMapLoader(path string) ([]byte, error) { func (c *Compiler) compileImpl( src, filename string, wrap bool, compatibilityMode lib.CompatibilityMode, srcMap []byte, -) (*goja.Program, string, error) { +) (*sobek.Program, string, error) { code := src state := compilationState{srcMap: srcMap, compiler: c, wrapped: wrap} if wrap { @@ -241,7 +241,7 @@ func (c *Compiler) compileImpl( } if err == nil { - pgm, err := goja.CompileAST(ast, c.Options.Strict) + pgm, err := sobek.CompileAST(ast, c.Options.Strict) return pgm, code, err } @@ -269,20 +269,20 @@ func (c *Compiler) compileImpl( } type babel struct { - vm *goja.Runtime - this goja.Value - transform goja.Callable + vm *sobek.Runtime + this sobek.Value + transform sobek.Callable m sync.Mutex } func newBabel() (*babel, error) { onceBabelCode.Do(func() { - globalBabelCode, errGlobalBabelCode = goja.Compile("", babelSrc, false) + globalBabelCode, errGlobalBabelCode = sobek.Compile("", babelSrc, false) }) if errGlobalBabelCode != nil { return nil, errGlobalBabelCode } - vm := goja.New() + vm := sobek.New() _, err := vm.RunProgram(globalBabelCode) if err != nil { return nil, err @@ -404,8 +404,8 @@ func (b *babel) transformImpl( if err != nil { return code, nil, err } - c, _ := goja.AssertFunction(stringify) - mapAsJSON, err := c(goja.Undefined(), vO.Get("map")) + c, _ := sobek.AssertFunction(stringify) + mapAsJSON, err := c(sobek.Undefined(), vO.Get("map")) if err != nil { return code, nil, err } diff --git a/js/compiler/compiler_test.go b/js/compiler/compiler_test.go index 6f8ae53b782..22c90503518 100644 --- a/js/compiler/compiler_test.go +++ b/js/compiler/compiler_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -73,7 +73,7 @@ func TestCompile(t *testing.T) { pgm, code, err := c.Compile(src, "script.js", true) require.NoError(t, err) assert.Equal(t, src, code) - v, err := goja.New().RunProgram(pgm) + v, err := sobek.New().RunProgram(pgm) require.NoError(t, err) assert.Equal(t, int64(3), v.Export()) }) @@ -85,13 +85,13 @@ func TestCompile(t *testing.T) { pgm, code, err := c.Compile(src, "script.js", false) require.NoError(t, err) assert.Equal(t, "(function(module, exports){exports.d=1+(function() { return 2; })()\n})\n", code) - rt := goja.New() + rt := sobek.New() v, err := rt.RunProgram(pgm) require.NoError(t, err) - fn, ok := goja.AssertFunction(v) + fn, ok := sobek.AssertFunction(v) require.True(t, ok, "not a function") - exp := make(map[string]goja.Value) - _, err = fn(goja.Undefined(), goja.Undefined(), rt.ToValue(exp)) + exp := make(map[string]sobek.Value) + _, err = fn(sobek.Undefined(), sobek.Undefined(), rt.ToValue(exp)) require.NoError(t, err) assert.Equal(t, int64(3), exp["d"].Export()) }) @@ -102,7 +102,7 @@ func TestCompile(t *testing.T) { src := `1+(function() { return 2; )()` c.Options.CompatibilityMode = lib.CompatibilityModeExtended _, _, err := c.Compile(src, "script.js", false) - assert.IsType(t, &goja.Exception{}, err) + assert.IsType(t, &sobek.Exception{}, err) assert.Contains(t, err.Error(), `SyntaxError: script.js: Unexpected token (1:26) > 1 | 1+(function() { return 2; )()`) }) @@ -114,7 +114,7 @@ func TestCompile(t *testing.T) { require.NoError(t, err) assert.Equal(t, `"use strict";require("something");`, code) - rt := goja.New() + rt := sobek.New() var requireCalled bool require.NoError(t, rt.Set("require", func(s string) { assert.Equal(t, "something", s) @@ -135,16 +135,16 @@ func TestCompile(t *testing.T) { }) `, code) var requireCalled bool - rt := goja.New() + rt := sobek.New() require.NoError(t, rt.Set("require", func(s string) { assert.Equal(t, "something", s) requireCalled = true })) v, err := rt.RunProgram(pgm) require.NoError(t, err) - fn, ok := goja.AssertFunction(v) + fn, ok := sobek.AssertFunction(v) require.True(t, ok, "not a function") - _, err = fn(goja.Undefined()) + _, err = fn(sobek.Undefined()) assert.NoError(t, err) require.True(t, requireCalled) }) @@ -154,7 +154,7 @@ func TestCompile(t *testing.T) { c := New(testutils.NewLogger(t)) c.Options.CompatibilityMode = lib.CompatibilityModeExtended _, _, err := c.Compile(`1+(=>2)()`, "script.js", true) - assert.IsType(t, &goja.Exception{}, err) + assert.IsType(t, &sobek.Exception{}, err) assert.Contains(t, err.Error(), `SyntaxError: script.js: Unexpected token (1:3) > 1 | 1+(=>2)()`) }) diff --git a/js/compiler/enhanced_test.go b/js/compiler/enhanced_test.go index c272861977d..4e06f694d9c 100644 --- a/js/compiler/enhanced_test.go +++ b/js/compiler/enhanced_test.go @@ -4,8 +4,8 @@ import ( "errors" "testing" - "github.com/dop251/goja" "github.com/dop251/goja/parser" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.k6.io/k6/lib" @@ -73,7 +73,7 @@ func TestCompile_experimental_enhanced(t *testing.T) { require.NoError(t, err) assert.Equal(t, `var import_something = require("something"); `, code) - rt := goja.New() + rt := sobek.New() var requireCalled bool require.NoError(t, rt.Set("require", func(s string) { assert.Equal(t, "something", s) diff --git a/js/console.go b/js/console.go index 7da10f54407..32b0440c7ca 100644 --- a/js/console.go +++ b/js/console.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" ) @@ -35,7 +35,7 @@ func newFileConsole(filepath string, formatter logrus.Formatter, level logrus.Le return &console{l}, nil } -func (c console) log(level logrus.Level, args ...goja.Value) { +func (c console) log(level logrus.Level, args ...sobek.Value) { var strs strings.Builder for i := 0; i < len(args); i++ { if i > 0 { @@ -57,27 +57,27 @@ func (c console) log(level logrus.Level, args ...goja.Value) { } } -func (c console) Log(args ...goja.Value) { +func (c console) Log(args ...sobek.Value) { c.Info(args...) } -func (c console) Debug(args ...goja.Value) { +func (c console) Debug(args ...sobek.Value) { c.log(logrus.DebugLevel, args...) } -func (c console) Info(args ...goja.Value) { +func (c console) Info(args ...sobek.Value) { c.log(logrus.InfoLevel, args...) } -func (c console) Warn(args ...goja.Value) { +func (c console) Warn(args ...sobek.Value) { c.log(logrus.WarnLevel, args...) } -func (c console) Error(args ...goja.Value) { +func (c console) Error(args ...sobek.Value) { c.log(logrus.ErrorLevel, args...) } -func (c console) valueString(v goja.Value) string { +func (c console) valueString(v sobek.Value) string { mv, ok := v.(json.Marshaler) if !ok { return v.String() diff --git a/js/console_test.go b/js/console_test.go index f531116cc23..ba0be0ebf2f 100644 --- a/js/console_test.go +++ b/js/console_test.go @@ -8,7 +8,7 @@ import ( "os" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" logtest "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/assert" @@ -25,7 +25,7 @@ import ( func TestConsoleContext(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) logger, hook := logtest.NewNullLogger() @@ -104,7 +104,7 @@ func extractLogger(vu lib.ActiveVU) *logrus.Logger { func TestConsoleLogWithGojaNativeObject(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) obj := rt.NewObject() @@ -163,7 +163,7 @@ func TestConsoleLogObjectsWithGoTypes(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) obj := rt.ToValue(tt.in) diff --git a/js/eventloop/eventloop.go b/js/eventloop/eventloop.go index 615da8959ad..09a11cf60e5 100644 --- a/js/eventloop/eventloop.go +++ b/js/eventloop/eventloop.go @@ -5,7 +5,7 @@ import ( "fmt" "sync" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/modules" ) @@ -31,7 +31,7 @@ type EventLoop struct { // pendingPromiseRejections are rejected promises with no handler, // if there is something in this map at an end of an event loop then it will exit with an error. // It's similar to what Deno and Node do. - pendingPromiseRejections map[*goja.Promise]struct{} + pendingPromiseRejections map[*sobek.Promise]struct{} } // New returns a new event loop with a few helpers attached to it: @@ -40,7 +40,7 @@ type EventLoop struct { func New(vu modules.VU) *EventLoop { e := &EventLoop{ wakeupCh: make(chan struct{}, 1), - pendingPromiseRejections: make(map[*goja.Promise]struct{}), + pendingPromiseRejections: make(map[*sobek.Promise]struct{}), vu: vu, } vu.Runtime().SetPromiseRejectionTracker(e.promiseRejectionTracker) @@ -82,7 +82,7 @@ func (e *EventLoop) wakeup() { // // A common pattern for async work is something like this: // -// func doAsyncWork(vu modules.VU) *goja.Promise { +// func doAsyncWork(vu modules.VU) *sobek.Promise { // enqueueCallback := vu.RegisterCallback() // p, resolve, reject := vu.Runtime().NewPromise() // @@ -131,12 +131,12 @@ func (e *EventLoop) RegisterCallback() (enqueueCallback func(func() error)) { } } -func (e *EventLoop) promiseRejectionTracker(p *goja.Promise, op goja.PromiseRejectionOperation) { +func (e *EventLoop) promiseRejectionTracker(p *sobek.Promise, op sobek.PromiseRejectionOperation) { // No locking necessary here as the goja runtime will call this synchronously // Read Notes on https://tc39.es/ecma262/#sec-host-promise-rejection-tracker - if op == goja.PromiseRejectionReject { + if op == sobek.PromiseRejectionReject { e.pendingPromiseRejections[p] = struct{}{} - } else { // goja.PromiseRejectionHandle so a promise that was previously rejected without handler now got one + } else { // sobek.PromiseRejectionHandle so a promise that was previously rejected without handler now got one delete(e.pendingPromiseRejections, p) } } @@ -160,7 +160,7 @@ func (e *EventLoop) putInfront(queue []func() error) { // or a queued function returns an error. The provided firstCallback will be the first thing executed. // After Start returns the event loop can be reused as long as waitOnRegistered is called. func (e *EventLoop) Start(firstCallback func() error) error { - e.pendingPromiseRejections = make(map[*goja.Promise]struct{}) + e.pendingPromiseRejections = make(map[*sobek.Promise]struct{}) e.queue = []func() error{firstCallback} for { queue, awaiting := e.popAll() @@ -185,7 +185,7 @@ func (e *EventLoop) Start(firstCallback func() error) error { // But that seems to be the case in other tools as well so it seems to not be that big of a problem. for promise := range e.pendingPromiseRejections { value := promise.Result() - if !goja.IsNull(value) && !goja.IsUndefined(value) { + if !sobek.IsNull(value) && !sobek.IsUndefined(value) { if o := value.ToObject(e.vu.Runtime()); o != nil { if stack := o.Get("stack"); stack != nil { value = stack diff --git a/js/eventloop/eventloop_test.go b/js/eventloop/eventloop_test.go index f15d79ed4e3..085c1cfcd13 100644 --- a/js/eventloop/eventloop_test.go +++ b/js/eventloop/eventloop_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/require" "go.k6.io/k6/js/common" "go.k6.io/k6/js/eventloop" @@ -16,7 +16,7 @@ import ( func TestBasicEventLoop(t *testing.T) { t.Parallel() - loop := eventloop.New(&modulestest.VU{RuntimeField: goja.New()}) + loop := eventloop.New(&modulestest.VU{RuntimeField: sobek.New()}) var ran int f := func() error { //nolint:unparam ran++ @@ -36,7 +36,7 @@ func TestBasicEventLoop(t *testing.T) { func TestEventLoopRegistered(t *testing.T) { t.Parallel() - loop := eventloop.New(&modulestest.VU{RuntimeField: goja.New()}) + loop := eventloop.New(&modulestest.VU{RuntimeField: sobek.New()}) var ran int f := func() error { ran++ @@ -61,7 +61,7 @@ func TestEventLoopRegistered(t *testing.T) { func TestEventLoopWaitOnRegistered(t *testing.T) { t.Parallel() var ran int - loop := eventloop.New(&modulestest.VU{RuntimeField: goja.New()}) + loop := eventloop.New(&modulestest.VU{RuntimeField: sobek.New()}) f := func() error { ran++ r := loop.RegisterCallback() @@ -88,7 +88,7 @@ func TestEventLoopWaitOnRegistered(t *testing.T) { func TestEventLoopAllCallbacksGetCalled(t *testing.T) { t.Parallel() sleepTime := time.Millisecond * 500 - loop := eventloop.New(&modulestest.VU{RuntimeField: goja.New()}) + loop := eventloop.New(&modulestest.VU{RuntimeField: sobek.New()}) var called int64 f := func() error { for i := 0; i < 100; i++ { @@ -126,7 +126,7 @@ func TestEventLoopAllCallbacksGetCalled(t *testing.T) { func TestEventLoopPanicOnDoubleCallback(t *testing.T) { t.Parallel() - loop := eventloop.New(&modulestest.VU{RuntimeField: goja.New()}) + loop := eventloop.New(&modulestest.VU{RuntimeField: sobek.New()}) var ran int f := func() error { ran++ @@ -152,7 +152,7 @@ func TestEventLoopPanicOnDoubleCallback(t *testing.T) { func TestEventLoopRejectUndefined(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) err := loop.Start(func() error { _, err := vu.Runtime().RunString("Promise.reject()") @@ -164,7 +164,7 @@ func TestEventLoopRejectUndefined(t *testing.T) { func TestEventLoopRejectString(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) err := loop.Start(func() error { _, err := vu.Runtime().RunString("Promise.reject('some string')") @@ -176,7 +176,7 @@ func TestEventLoopRejectString(t *testing.T) { func TestEventLoopRejectSyntaxError(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) err := loop.Start(func() error { _, err := vu.Runtime().RunString("Promise.resolve().then(()=> {some.syntax.error})") @@ -188,7 +188,7 @@ func TestEventLoopRejectSyntaxError(t *testing.T) { func TestEventLoopRejectGoError(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) rt := vu.Runtime() require.NoError(t, rt.Set("f", rt.ToValue(func() error { @@ -204,7 +204,7 @@ func TestEventLoopRejectGoError(t *testing.T) { func TestEventLoopRejectThrow(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) rt := vu.Runtime() require.NoError(t, rt.Set("f", rt.ToValue(func() error { @@ -221,7 +221,7 @@ func TestEventLoopRejectThrow(t *testing.T) { func TestEventLoopAsyncAwait(t *testing.T) { t.Parallel() - vu := &modulestest.VU{RuntimeField: goja.New()} + vu := &modulestest.VU{RuntimeField: sobek.New()} loop := eventloop.New(vu) err := loop.Start(func() error { _, err := vu.Runtime().RunString(` diff --git a/js/initcontext.go b/js/initcontext.go index 8f6c0eb400c..80cd7903c06 100644 --- a/js/initcontext.go +++ b/js/initcontext.go @@ -5,7 +5,7 @@ import ( "fmt" "net/url" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "go.k6.io/k6/lib/fsext" @@ -18,7 +18,7 @@ const cantBeUsedOutsideInitContextMsg = `the "%s" function is only available in // openImpl implements openImpl() in the init context and will read and return the // contents of a file. If the second argument is "b" it returns an ArrayBuffer // instance, otherwise a string representation. -func openImpl(rt *goja.Runtime, fs fsext.Fs, basePWD *url.URL, filename string, args ...string) (goja.Value, error) { +func openImpl(rt *sobek.Runtime, fs fsext.Fs, basePWD *url.URL, filename string, args ...string) (sobek.Value, error) { data, err := readFile(fs, fsext.Abs(basePWD.Path, filename)) if err != nil { return nil, err diff --git a/js/initcontext_test.go b/js/initcontext_test.go index f89ed46b27e..0cfd210242c 100644 --- a/js/initcontext_test.go +++ b/js/initcontext_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -47,13 +47,13 @@ func TestRequire(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) assert.NoError(t, err, "instance error") - _, defaultOk := goja.AssertFunction(bi.getExported("default")) + _, defaultOk := sobek.AssertFunction(bi.getExported("default")) assert.True(t, defaultOk, "default export is not a function") assert.Equal(t, "abc123", bi.getExported("dummy").String()) k6 := bi.getExported("_k6").ToObject(bi.Runtime) require.NotNil(t, k6) - _, groupOk := goja.AssertFunction(k6.Get("group")) + _, groupOk := sobek.AssertFunction(k6.Get("group")) assert.True(t, groupOk, "k6.group is not a function") }) @@ -70,11 +70,11 @@ func TestRequire(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, defaultOk := goja.AssertFunction(bi.getExported("default")) + _, defaultOk := sobek.AssertFunction(bi.getExported("default")) assert.True(t, defaultOk, "default export is not a function") assert.Equal(t, "abc123", bi.getExported("dummy").String()) - _, groupOk := goja.AssertFunction(bi.getExported("_group")) + _, groupOk := sobek.AssertFunction(bi.getExported("_group")) assert.True(t, groupOk, "{ group } is not a function") }) }) @@ -196,7 +196,7 @@ func TestRequire(t *testing.T) { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) assert.NoError(t, err) }) }) @@ -370,7 +370,7 @@ func TestRequestWithBinaryFile(t *testing.T) { defer cancel() bi.moduleVUImpl.ctx = ctx - v, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + v, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.NotNil(t, v) assert.Equal(t, true, v.Export()) @@ -512,7 +512,7 @@ func TestRequestWithMultipleBinaryFiles(t *testing.T) { defer cancel() bi.moduleVUImpl.ctx = ctx - v, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + v, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) require.NotNil(t, v) assert.Equal(t, true, v.Export()) @@ -529,7 +529,7 @@ func Test__VU(t *testing.T) { require.NoError(t, err) bi, err := b.Instantiate(context.Background(), 5) require.NoError(t, err) - v, err := bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + v, err := bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.NoError(t, err) assert.Equal(t, int64(5), v.Export()) } @@ -561,9 +561,9 @@ export default function(){ bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) require.Equal(t, exception.String(), "exception in line 2\n\tat f2 (file:///module1.js:2:4(2))\n\tat file:///script.js:5:4(3)\n") } @@ -595,9 +595,9 @@ export default function(){ bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) require.Equal(t, exception.String(), "exception in line 2\n\tat file:///module1.js:2:5(2)\n\tat file:///script.js:5:4(3)\n") } @@ -625,9 +625,9 @@ export default function () { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) require.Equal(t, "cool is cool\n\tat webpack:///./test1.ts:2:4(2)\n\tat webpack:///./test1.ts:5:4(3)\n\tat file:///script.js:4:2(4)\n", exception.String()) } @@ -656,9 +656,9 @@ export default function () { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) // TODO figure out why those are not the same as the one in the previous test TestSourceMapsExternal // likely settings in the transpilers @@ -686,9 +686,9 @@ export default function () { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) // TODO figure out why those are not the same as the one in the previous test TestSourceMapsExternal // likely settings in the transpilers @@ -756,9 +756,9 @@ var script_default = () => { bi, err := b.Instantiate(context.Background(), 0) require.NoError(t, err) - _, err = bi.getCallableExport(consts.DefaultFn)(goja.Undefined()) + _, err = bi.getCallableExport(consts.DefaultFn)(sobek.Undefined()) require.Error(t, err) - exception := new(goja.Exception) + exception := new(sobek.Exception) require.ErrorAs(t, err, &exception) // TODO figure out why those are not the same as the one in the previous test TestSourceMapsExternal // likely settings in the transpilers diff --git a/js/modules/cjsmodule.go b/js/modules/cjsmodule.go index bbde855211e..495e0a9f63a 100644 --- a/js/modules/cjsmodule.go +++ b/js/modules/cjsmodule.go @@ -4,14 +4,14 @@ import ( "fmt" "net/url" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/compiler" ) // cjsModule represents a commonJS module type cjsModule struct { - prg *goja.Program + prg *sobek.Program url *url.URL } @@ -19,7 +19,7 @@ var _ module = &cjsModule{} type cjsModuleInstance struct { mod *cjsModule - moduleObj *goja.Object + moduleObj *sobek.Object vu VU } @@ -42,7 +42,7 @@ func (c *cjsModuleInstance) execute() error { if err != nil { return err } - if call, ok := goja.AssertFunction(f); ok { + if call, ok := sobek.AssertFunction(f); ok { if _, err = call(exports, c.moduleObj, exports); err != nil { return err } @@ -51,7 +51,7 @@ func (c *cjsModuleInstance) execute() error { return nil } -func (c *cjsModuleInstance) exports() *goja.Object { +func (c *cjsModuleInstance) exports() *sobek.Object { exportsV := c.moduleObj.Get("exports") if common.IsNullish(exportsV) { return nil diff --git a/js/modules/gomodule.go b/js/modules/gomodule.go index c634575376e..b495cfa23c3 100644 --- a/js/modules/gomodule.go +++ b/js/modules/gomodule.go @@ -1,7 +1,7 @@ package modules import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" ) // baseGoModule is a go module that does not implement modules.Module interface @@ -19,14 +19,14 @@ func (b *baseGoModule) instantiate(vu VU) moduleInstance { type baseGoModuleInstance struct { mod interface{} vu VU - exportsO *goja.Object // this is so we only initialize the exports once per instance + exportsO *sobek.Object // this is so we only initialize the exports once per instance } func (b *baseGoModuleInstance) execute() error { return nil } -func (b *baseGoModuleInstance) exports() *goja.Object { +func (b *baseGoModuleInstance) exports() *sobek.Object { if b.exportsO == nil { // TODO check this does not panic a lot rt := b.vu.Runtime() @@ -50,7 +50,7 @@ type goModuleInstance struct { Instance module *goModule vu VU - exportsO *goja.Object // this is so we only initialize the exports once per instance + exportsO *sobek.Object // this is so we only initialize the exports once per instance } var _ moduleInstance = &goModuleInstance{} @@ -60,7 +60,7 @@ func (gi *goModuleInstance) execute() error { return nil } -func (gi *goModuleInstance) exports() *goja.Object { +func (gi *goModuleInstance) exports() *sobek.Object { if gi.exportsO == nil { rt := gi.vu.Runtime() gi.exportsO = rt.ToValue(toESModuleExports(gi.Instance.Exports())).ToObject(rt) diff --git a/js/modules/k6/crypto/crypto.go b/js/modules/k6/crypto/crypto.go index 8eee7ad7121..728a6648d6f 100644 --- a/js/modules/k6/crypto/crypto.go +++ b/js/modules/k6/crypto/crypto.go @@ -17,7 +17,7 @@ import ( "golang.org/x/crypto/md4" //nolint:staticcheck // #nosec G501 // MD4 is weak, but we need it for compatibility "golang.org/x/crypto/ripemd160" // no lint:staticcheck // #nosec G501 // RIPEMD160 is weak, but we need it for compatibility - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" @@ -74,7 +74,7 @@ func (c *Crypto) Exports() modules.Exports { } // randomBytes returns random data of the given size. -func (c *Crypto) randomBytes(size int) (*goja.ArrayBuffer, error) { +func (c *Crypto) randomBytes(size int) (*sobek.ArrayBuffer, error) { if size < 1 { return nil, errors.New("invalid size") } @@ -215,9 +215,9 @@ func (c *Crypto) parseHashFunc(a string) func() hash.Hash { return h } -// Hasher wraps an hash.Hash with goja.Runtime. +// Hasher wraps an hash.Hash with sobek.Runtime. type Hasher struct { - runtime *goja.Runtime + runtime *sobek.Runtime hash hash.Hash } diff --git a/js/modules/k6/crypto/crypto_test.go b/js/modules/k6/crypto/crypto_test.go index 7e4138c63fc..f0aff7c54a3 100644 --- a/js/modules/k6/crypto/crypto_test.go +++ b/js/modules/k6/crypto/crypto_test.go @@ -6,7 +6,7 @@ import ( "fmt" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -20,8 +20,8 @@ func (MockReader) Read(_ []byte) (int, error) { return -1, errors.New("Contrived failure") } -func makeRuntime(t *testing.T) *goja.Runtime { - rt := goja.New() +func makeRuntime(t *testing.T) *sobek.Runtime { + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) m, ok := New().NewModuleInstance( @@ -73,7 +73,7 @@ func TestCryptoAlgorithms(t *testing.T) { t.Run("RandomBytesFailure", func(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) m, ok := New().NewModuleInstance( @@ -501,7 +501,7 @@ func TestHexEncode(t *testing.T) { t.Parallel() t.Run("Success", func(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() input := []byte{104, 101, 108, 108, 111} testCases := []interface{}{ input, string(input), rt.NewArrayBuffer(input), @@ -522,7 +522,7 @@ func TestHexEncode(t *testing.T) { t.Parallel() c := Crypto{vu: &modulestest.VU{ - RuntimeField: goja.New(), + RuntimeField: sobek.New(), }} _, err := c.hexEncode(struct{}{}) @@ -534,7 +534,7 @@ func TestAWSv4(t *testing.T) { t.Parallel() // example values from https://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) m, ok := New().NewModuleInstance( diff --git a/js/modules/k6/crypto/x509/x509_test.go b/js/modules/k6/crypto/x509/x509_test.go index 7474e1e4afa..e5ef0ec7670 100644 --- a/js/modules/k6/crypto/x509/x509_test.go +++ b/js/modules/k6/crypto/x509/x509_test.go @@ -6,7 +6,7 @@ import ( "fmt" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,8 +14,8 @@ import ( "go.k6.io/k6/js/modulestest" ) -func makeRuntime(t *testing.T) *goja.Runtime { - rt := goja.New() +func makeRuntime(t *testing.T) *sobek.Runtime { + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) m, ok := New().NewModuleInstance( &modulestest.VU{ diff --git a/js/modules/k6/data/data.go b/js/modules/k6/data/data.go index d1df6382a5e..9e5ad78fa8b 100644 --- a/js/modules/k6/data/data.go +++ b/js/modules/k6/data/data.go @@ -7,7 +7,7 @@ import ( "strconv" "sync" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) @@ -67,7 +67,7 @@ const asyncFunctionNotSupportedMsg = "SharedArray constructor does not support a // sharedArray is a constructor returning a shareable read-only array // indentified by the name and having their contents be whatever the call returns -func (d *Data) sharedArray(call goja.ConstructorCall) *goja.Object { +func (d *Data) sharedArray(call sobek.ConstructorCall) *sobek.Object { rt := d.vu.Runtime() if d.vu.State() != nil { @@ -84,7 +84,7 @@ func (d *Data) sharedArray(call goja.ConstructorCall) *goja.Object { common.Throw(rt, errors.New(asyncFunctionNotSupportedMsg)) } - fn, ok := goja.AssertFunction(val) + fn, ok := sobek.AssertFunction(val) if !ok { common.Throw(rt, errors.New("a function is expected as the second argument of SharedArray's constructor")) } @@ -93,7 +93,7 @@ func (d *Data) sharedArray(call goja.ConstructorCall) *goja.Object { return array.wrap(rt).ToObject(rt) } -func (s *sharedArrays) get(rt *goja.Runtime, name string, call goja.Callable) sharedArray { +func (s *sharedArrays) get(rt *sobek.Runtime, name string, call sobek.Callable) sharedArray { s.mu.RLock() array, ok := s.data[name] s.mu.RUnlock() @@ -110,8 +110,8 @@ func (s *sharedArrays) get(rt *goja.Runtime, name string, call goja.Callable) sh return array } -func getShareArrayFromCall(rt *goja.Runtime, call goja.Callable) sharedArray { - gojaValue, err := call(goja.Undefined()) +func getShareArrayFromCall(rt *sobek.Runtime, call sobek.Callable) sharedArray { + gojaValue, err := call(sobek.Undefined()) if err != nil { common.Throw(rt, err) } @@ -121,10 +121,10 @@ func getShareArrayFromCall(rt *goja.Runtime, call goja.Callable) sharedArray { } arr := make([]string, obj.Get("length").ToInteger()) - stringify, _ := goja.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("stringify")) - var val goja.Value + stringify, _ := sobek.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("stringify")) + var val sobek.Value for i := range arr { - val, err = stringify(goja.Undefined(), obj.Get(strconv.Itoa(i))) + val, err = stringify(sobek.Undefined(), obj.Get(strconv.Itoa(i))) if err != nil { panic(err) } diff --git a/js/modules/k6/data/share.go b/js/modules/k6/data/share.go index 828726cc38f..9c4b8fee44a 100644 --- a/js/modules/k6/data/share.go +++ b/js/modules/k6/data/share.go @@ -1,7 +1,7 @@ package data import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" ) @@ -14,16 +14,16 @@ type sharedArray struct { type wrappedSharedArray struct { sharedArray - rt *goja.Runtime - freeze goja.Callable - isFrozen goja.Callable - parse goja.Callable + rt *sobek.Runtime + freeze sobek.Callable + isFrozen sobek.Callable + parse sobek.Callable } -func (s sharedArray) wrap(rt *goja.Runtime) goja.Value { - freeze, _ := goja.AssertFunction(rt.GlobalObject().Get("Object").ToObject(rt).Get("freeze")) - isFrozen, _ := goja.AssertFunction(rt.GlobalObject().Get("Object").ToObject(rt).Get("isFrozen")) - parse, _ := goja.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("parse")) +func (s sharedArray) wrap(rt *sobek.Runtime) sobek.Value { + freeze, _ := sobek.AssertFunction(rt.GlobalObject().Get("Object").ToObject(rt).Get("freeze")) + isFrozen, _ := sobek.AssertFunction(rt.GlobalObject().Get("Object").ToObject(rt).Get("isFrozen")) + parse, _ := sobek.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("parse")) return rt.NewDynamicArray(wrappedSharedArray{ sharedArray: s, rt: rt, @@ -33,7 +33,7 @@ func (s sharedArray) wrap(rt *goja.Runtime) goja.Value { }) } -func (s wrappedSharedArray) Set(_ int, _ goja.Value) bool { +func (s wrappedSharedArray) Set(_ int, _ sobek.Value) bool { panic(s.rt.NewTypeError("SharedArray is immutable")) // this is specifically a type error } @@ -41,11 +41,11 @@ func (s wrappedSharedArray) SetLen(_ int) bool { panic(s.rt.NewTypeError("SharedArray is immutable")) // this is specifically a type error } -func (s wrappedSharedArray) Get(index int) goja.Value { +func (s wrappedSharedArray) Get(index int) sobek.Value { if index < 0 || index >= len(s.arr) { - return goja.Undefined() + return sobek.Undefined() } - val, err := s.parse(goja.Undefined(), s.rt.ToValue(s.arr[index])) + val, err := s.parse(sobek.Undefined(), s.rt.ToValue(s.arr[index])) if err != nil { common.Throw(s.rt, err) } @@ -61,12 +61,12 @@ func (s wrappedSharedArray) Len() int { return len(s.arr) } -func (s wrappedSharedArray) deepFreeze(rt *goja.Runtime, val goja.Value) error { - if val != nil && goja.IsNull(val) { +func (s wrappedSharedArray) deepFreeze(rt *sobek.Runtime, val sobek.Value) error { + if val != nil && sobek.IsNull(val) { return nil } - _, err := s.freeze(goja.Undefined(), val) + _, err := s.freeze(sobek.Undefined(), val) if err != nil { return err } @@ -79,7 +79,7 @@ func (s wrappedSharedArray) deepFreeze(rt *goja.Runtime, val goja.Value) error { prop := o.Get(key) if prop != nil { // isFrozen returns true for all non objects so it we don't need to check that - frozen, err := s.isFrozen(goja.Undefined(), prop) + frozen, err := s.isFrozen(sobek.Undefined(), prop) if err != nil { return err } diff --git a/js/modules/k6/data/share_test.go b/js/modules/k6/data/share_test.go index abf53903530..d25559a7679 100644 --- a/js/modules/k6/data/share_test.go +++ b/js/modules/k6/data/share_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/require" "go.k6.io/k6/js/common" @@ -102,7 +102,7 @@ func TestSharedArrayConstructorExceptions(t *testing.T) { } require.Error(t, err) - exc := new(goja.Exception) + exc := new(sobek.Exception) require.True(t, errors.As(err, &exc)) require.Contains(t, exc.Error(), testCase.err) }) @@ -156,7 +156,7 @@ func TestSharedArrayAnotherRuntimeExceptions(t *testing.T) { } require.Error(t, err) - exc := new(goja.Exception) + exc := new(sobek.Exception) require.True(t, errors.As(err, &exc)) require.Contains(t, exc.Error(), testCase.err) }) @@ -166,7 +166,7 @@ func TestSharedArrayAnotherRuntimeExceptions(t *testing.T) { func TestSharedArrayAnotherRuntimeWorking(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() vu := &modulestest.VU{ RuntimeField: rt, InitEnvField: &common.InitEnvironment{}, @@ -181,7 +181,7 @@ func TestSharedArrayAnotherRuntimeWorking(t *testing.T) { require.NoError(t, err) // create another Runtime with new ctx but keep the initEnv - rt = goja.New() + rt = sobek.New() vu.RuntimeField = rt vu.CtxField = context.Background() require.NoError(t, rt.Set("data", m.Exports().Named)) @@ -224,7 +224,7 @@ func TestSharedArrayRaceInInitialization(t *testing.T) { const instances = 10 const repeats = 100 for i := 0; i < repeats; i++ { - runtimes := make([]*goja.Runtime, instances) + runtimes := make([]*sobek.Runtime, instances) for j := 0; j < instances; j++ { runtime, err := newConfiguredRuntime(t) require.NoError(t, err) diff --git a/js/modules/k6/encoding/encoding_test.go b/js/modules/k6/encoding/encoding_test.go index 807fd787556..2d613acbb32 100644 --- a/js/modules/k6/encoding/encoding_test.go +++ b/js/modules/k6/encoding/encoding_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -12,8 +12,8 @@ import ( "go.k6.io/k6/js/modulestest" ) -func makeRuntime(t *testing.T) *goja.Runtime { - rt := goja.New() +func makeRuntime(t *testing.T) *sobek.Runtime { + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) m, ok := New().NewModuleInstance( &modulestest.VU{ diff --git a/js/modules/k6/execution/execution.go b/js/modules/k6/execution/execution.go index 001cc403cd1..6393b1d9c2f 100644 --- a/js/modules/k6/execution/execution.go +++ b/js/modules/k6/execution/execution.go @@ -7,7 +7,7 @@ import ( "fmt" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/errext" "go.k6.io/k6/js/common" @@ -24,7 +24,7 @@ type ( // ModuleInstance represents an instance of the execution module. ModuleInstance struct { vu modules.VU - obj *goja.Object + obj *sobek.Object } ) @@ -44,14 +44,14 @@ func (*RootModule) NewModuleInstance(vu modules.VU) modules.Instance { mi := &ModuleInstance{vu: vu} rt := vu.Runtime() o := rt.NewObject() - defProp := func(name string, newInfo func() (*goja.Object, error)) { - err := o.DefineAccessorProperty(name, rt.ToValue(func() goja.Value { + defProp := func(name string, newInfo func() (*sobek.Object, error)) { + err := o.DefineAccessorProperty(name, rt.ToValue(func() sobek.Value { obj, err := newInfo() if err != nil { common.Throw(rt, err) } return obj - }), nil, goja.FLAG_FALSE, goja.FLAG_TRUE) + }), nil, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { common.Throw(rt, err) } @@ -73,9 +73,9 @@ func (mi *ModuleInstance) Exports() modules.Exports { var errRunInInitContext = errors.New("getting scenario information outside of the VU context is not supported") -// newScenarioInfo returns a goja.Object with property accessors to retrieve +// newScenarioInfo returns a sobek.Object with property accessors to retrieve // information about the scenario the current VU is running in. -func (mi *ModuleInstance) newScenarioInfo() (*goja.Object, error) { +func (mi *ModuleInstance) newScenarioInfo() (*sobek.Object, error) { rt := mi.vu.Runtime() vuState := mi.vu.State() if vuState == nil { @@ -130,9 +130,9 @@ func (mi *ModuleInstance) newScenarioInfo() (*goja.Object, error) { //nolint:lll,gochecknoglobals var instanceInfoInitContextErr = common.NewInitContextError("getting instance information in the init context is not supported") -// newInstanceInfo returns a goja.Object with property accessors to retrieve +// newInstanceInfo returns a sobek.Object with property accessors to retrieve // information about the local instance stats. -func (mi *ModuleInstance) newInstanceInfo() (*goja.Object, error) { +func (mi *ModuleInstance) newInstanceInfo() (*sobek.Object, error) { es := lib.GetExecutionState(mi.vu.Context()) if es == nil { return nil, instanceInfoInitContextErr @@ -163,19 +163,19 @@ func (mi *ModuleInstance) newInstanceInfo() (*goja.Object, error) { //nolint:gochecknoglobals var testInfoInitContextErr = common.NewInitContextError("getting test options in the init context is not supported") -// newTestInfo returns a goja.Object with property accessors to retrieve +// newTestInfo returns a sobek.Object with property accessors to retrieve // information and control execution of the overall test run. -func (mi *ModuleInstance) newTestInfo() (*goja.Object, error) { - // the cache of goja.Object in the optimal parsed form +func (mi *ModuleInstance) newTestInfo() (*sobek.Object, error) { + // the cache of sobek.Object in the optimal parsed form // for the consolidated and derived lib.Options - var optionsObject *goja.Object + var optionsObject *sobek.Object rt := mi.vu.Runtime() ti := map[string]func() interface{}{ // stop the test run "abort": func() interface{} { - return func(msg goja.Value) { + return func(msg sobek.Value) { reason := errext.AbortTest - if msg != nil && !goja.IsUndefined(msg) { + if msg != nil && !sobek.IsUndefined(msg) { reason = fmt.Sprintf("%s: %s", reason, msg.String()) } rt.Interrupt(&errext.InterruptError{Reason: reason}) @@ -203,9 +203,9 @@ func (mi *ModuleInstance) newTestInfo() (*goja.Object, error) { //nolint:gochecknoglobals var vuInfoInitContextErr = common.NewInitContextError("getting VU information in the init context is not supported") -// newVUInfo returns a goja.Object with property accessors to retrieve +// newVUInfo returns a sobek.Object with property accessors to retrieve // information about the currently executing VU. -func (mi *ModuleInstance) newVUInfo() (*goja.Object, error) { +func (mi *ModuleInstance) newVUInfo() (*sobek.Object, error) { vuState := mi.vu.State() if vuState == nil { return nil, vuInfoInitContextErr @@ -262,11 +262,11 @@ func (mi *ModuleInstance) newVUInfo() (*goja.Object, error) { return o, err } -func newInfoObj(rt *goja.Runtime, props map[string]func() interface{}) (*goja.Object, error) { +func newInfoObj(rt *sobek.Runtime, props map[string]func() interface{}) (*sobek.Object, error) { o := rt.NewObject() for p, get := range props { - err := o.DefineAccessorProperty(p, rt.ToValue(get), nil, goja.FLAG_FALSE, goja.FLAG_TRUE) + err := o.DefineAccessorProperty(p, rt.ToValue(get), nil, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { return nil, err } @@ -276,11 +276,11 @@ func newInfoObj(rt *goja.Runtime, props map[string]func() interface{}) (*goja.Ob } // optionsAsObject maps the lib.Options struct that contains the consolidated -// and derived options configuration in a goja.Object. +// and derived options configuration in a sobek.Object. // // When values are not set then the default value returned from JSON is used. // Most of the lib.Options are Nullable types so they will be null on default. -func optionsAsObject(rt *goja.Runtime, options lib.Options) (*goja.Object, error) { +func optionsAsObject(rt *sobek.Runtime, options lib.Options) (*sobek.Object, error) { b, err := json.Marshal(options) if err != nil { return nil, fmt.Errorf("failed to encode the lib.Options as json: %w", err) @@ -288,8 +288,8 @@ func optionsAsObject(rt *goja.Runtime, options lib.Options) (*goja.Object, error // Using the native JS parser function guarantees getting // the supported types for deep freezing the complex object. - jsonParse, _ := goja.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("parse")) - parsed, err := jsonParse(goja.Undefined(), rt.ToValue(string(b))) + jsonParse, _ := sobek.AssertFunction(rt.GlobalObject().Get("JSON").ToObject(rt).Get("parse")) + parsed, err := jsonParse(sobek.Undefined(), rt.ToValue(string(b))) if err != nil { common.Throw(rt, err) } @@ -303,7 +303,7 @@ func optionsAsObject(rt *goja.Runtime, options lib.Options) (*goja.Object, error } } mustSetReadOnlyProperty := func(k string, v interface{}) { - defErr := obj.DefineDataProperty(k, rt.ToValue(v), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE) + defErr := obj.DefineDataProperty(k, rt.ToValue(v), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { common.Throw(rt, defErr) } @@ -314,13 +314,13 @@ func optionsAsObject(rt *goja.Runtime, options lib.Options) (*goja.Object, error mustDelete("duration") mustDelete("stages") - consoleOutput := goja.Null() + consoleOutput := sobek.Null() if options.ConsoleOutput.Valid { consoleOutput = rt.ToValue(options.ConsoleOutput.String) } mustSetReadOnlyProperty("consoleOutput", consoleOutput) - localIPs := goja.Null() + localIPs := sobek.Null() if options.LocalIPs.Valid { raw, marshalErr := options.LocalIPs.MarshalText() if err != nil { @@ -339,12 +339,12 @@ func optionsAsObject(rt *goja.Runtime, options lib.Options) (*goja.Object, error } type tagsDynamicObject struct { - runtime *goja.Runtime + runtime *sobek.Runtime state *lib.State } // Get a property value for the key. May return nil if the property does not exist. -func (o *tagsDynamicObject) Get(key string) goja.Value { +func (o *tagsDynamicObject) Get(key string) sobek.Value { tcv := o.state.Tags.GetCurrentValues() if tag, ok := tcv.Tags.Get(key); ok { return o.runtime.ToValue(tag) @@ -355,7 +355,7 @@ func (o *tagsDynamicObject) Get(key string) goja.Value { // Set a property value for the key. It returns true if succeed. String, Boolean // and Number types are implicitly converted to the goja's relative string // representation. An exception is raised in case a denied type is provided. -func (o *tagsDynamicObject) Set(key string, val goja.Value) bool { +func (o *tagsDynamicObject) Set(key string, val sobek.Value) bool { o.state.Tags.Modify(func(tagsAndMeta *metrics.TagsAndMeta) { if err := common.ApplyCustomUserTag(tagsAndMeta, key, val); err != nil { panic(o.runtime.NewTypeError(err.Error())) @@ -396,12 +396,12 @@ func (o *tagsDynamicObject) Keys() []string { } type metadataDynamicObject struct { - runtime *goja.Runtime + runtime *sobek.Runtime state *lib.State } // Get a property value for the key. May return nil if the property does not exist. -func (o *metadataDynamicObject) Get(key string) goja.Value { +func (o *metadataDynamicObject) Get(key string) sobek.Value { tcv := o.state.Tags.GetCurrentValues() if metadatum, ok := tcv.Metadata[key]; ok { return o.runtime.ToValue(metadatum) @@ -412,7 +412,7 @@ func (o *metadataDynamicObject) Get(key string) goja.Value { // Set a property value for the key. It returns true if successful. String, Boolean // and Number types are implicitly converted to the goja's relative string // representation. An exception is raised in case a denied type is provided. -func (o *metadataDynamicObject) Set(key string, val goja.Value) bool { +func (o *metadataDynamicObject) Set(key string, val sobek.Value) bool { o.state.Tags.Modify(func(tagsAndMeta *metrics.TagsAndMeta) { if err := common.ApplyCustomUserMetadata(tagsAndMeta, key, val); err != nil { panic(o.runtime.NewTypeError(err.Error())) diff --git a/js/modules/k6/execution/execution_test.go b/js/modules/k6/execution/execution_test.go index 35f522b4c23..114047de3f9 100644 --- a/js/modules/k6/execution/execution_test.go +++ b/js/modules/k6/execution/execution_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -186,7 +186,7 @@ func TestAbortTest(t *testing.T) { //nolint:tparallel t.Parallel() var ( - rt = goja.New() + rt = sobek.New() state = &lib.State{} ctx = context.Background() ) @@ -205,7 +205,7 @@ func TestAbortTest(t *testing.T) { //nolint:tparallel prove := func(t *testing.T, script, reason string) { _, err := rt.RunString(script) require.NotNil(t, err) - var x *goja.InterruptedError + var x *sobek.InterruptedError assert.ErrorAs(t, err, &x) v, ok := x.Value().(*errext.InterruptError) require.True(t, ok) @@ -226,7 +226,7 @@ func TestOptionsTestFull(t *testing.T) { expected := `{"paused":true,"scenarios":{"const-vus":{"executor":"constant-vus","options":{"browser":{"someOption":true}},"startTime":"10s","gracefulStop":"30s","env":{"FOO":"bar"},"exec":"default","tags":{"tagkey":"tagvalue"},"vus":50,"duration":"10m0s"}},"executionSegment":"0:1/4","executionSegmentSequence":"0,1/4,1/2,1","noSetup":true,"setupTimeout":"1m0s","noTeardown":true,"teardownTimeout":"5m0s","rps":100,"dns":{"ttl":"1m","select":"roundRobin","policy":"any"},"maxRedirects":3,"userAgent":"k6-user-agent","batch":15,"batchPerHost":5,"httpDebug":"full","insecureSkipTLSVerify":true,"tlsCipherSuites":["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"],"tlsVersion":{"min":"tls1.2","max":"tls1.3"},"tlsAuth":[{"domains":["example.com"],"cert":"mycert.pem","key":"mycert-key.pem","password":"mypwd"}],"throw":true,"thresholds":{"http_req_duration":[{"threshold":"rate>0.01","abortOnFail":true,"delayAbortEval":"10s"}]},"blacklistIPs":["192.0.2.0/24"],"blockHostnames":["test.k6.io","*.example.com"],"hosts":{"test.k6.io":"1.2.3.4:8443"},"noConnectionReuse":true,"noVUConnectionReuse":true,"minIterationDuration":"10s","ext":{"ext-one":{"rawkey":"rawvalue"}},"summaryTrendStats":["avg","min","max"],"summaryTimeUnit":"ms","systemTags":["iter","vu"],"tags":null,"metricSamplesBufferSize":8,"noCookiesReset":true,"discardResponseBodies":true,"consoleOutput":"loadtest.log","tags":{"runtag-key":"runtag-value"},"localIPs":"192.168.20.12-192.168.20.15,192.168.10.0/27"}` var ( - rt = goja.New() + rt = sobek.New() state = &lib.State{ Options: lib.Options{ Paused: null.BoolFrom(true), @@ -394,7 +394,7 @@ func TestOptionsTestFull(t *testing.T) { func TestOptionsTestSetPropertyDenied(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() m, ok := New().NewModuleInstance( &modulestest.VU{ RuntimeField: rt, @@ -419,7 +419,7 @@ func TestOptionsTestSetPropertyDenied(t *testing.T) { func TestScenarioNoAvailableInInitContext(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() m, ok := New().NewModuleInstance( &modulestest.VU{ RuntimeField: rt, @@ -447,7 +447,7 @@ func TestScenarioNoAvailableInInitContext(t *testing.T) { func TestOptionsNoAvailableInInitContext(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() m, ok := New().NewModuleInstance( &modulestest.VU{ RuntimeField: rt, @@ -464,7 +464,7 @@ func TestOptionsNoAvailableInInitContext(t *testing.T) { func TestVUDefaultDetails(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() m, ok := New().NewModuleInstance( &modulestest.VU{ RuntimeField: rt, @@ -491,7 +491,7 @@ func TestVUDefaultDetails(t *testing.T) { func TestTagsDynamicObjectGet(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() tdo := tagsDynamicObject{ runtime: rt, state: &lib.State{ @@ -505,7 +505,7 @@ func TestTagsDynamicObjectGet(t *testing.T) { func TestTagsDynamicObjectSet(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() tdo := tagsDynamicObject{ runtime: rt, state: &lib.State{ diff --git a/js/modules/k6/experimental/experimental.go b/js/modules/k6/experimental/experimental.go index 32dce96bce8..86a34f25cf4 100644 --- a/js/modules/k6/experimental/experimental.go +++ b/js/modules/k6/experimental/experimental.go @@ -5,7 +5,7 @@ import ( "errors" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) @@ -43,7 +43,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { } } -func (mi *ModuleInstance) setTimeout(f goja.Callable, t float64) { +func (mi *ModuleInstance) setTimeout(f sobek.Callable, t float64) { if f == nil { common.Throw(mi.vu.Runtime(), errors.New("setTimeout requires a function as first argument")) } @@ -55,7 +55,7 @@ func (mi *ModuleInstance) setTimeout(f goja.Callable, t float64) { select { case <-timer.C: runOnLoop(func() error { - _, err := f(goja.Undefined()) + _, err := f(sobek.Undefined()) return err }) case <-mi.vu.Context().Done(): diff --git a/js/modules/k6/experimental/fs/module.go b/js/modules/k6/experimental/fs/module.go index bfe5e861da9..6b20215df6d 100644 --- a/js/modules/k6/experimental/fs/module.go +++ b/js/modules/k6/experimental/fs/module.go @@ -9,7 +9,7 @@ import ( "fmt" "reflect" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/js/promises" @@ -64,7 +64,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { } // Open opens a file and returns a promise that will resolve to a [File] instance -func (mi *ModuleInstance) Open(path goja.Value) *goja.Promise { +func (mi *ModuleInstance) Open(path sobek.Value) *sobek.Promise { promise, resolve, reject := promises.New(mi.vu) if mi.vu.State() != nil { @@ -171,7 +171,7 @@ type File struct { // Stat returns a promise that will resolve to a [FileInfo] instance describing // the file. -func (f *File) Stat() *goja.Promise { +func (f *File) Stat() *sobek.Promise { promise, resolve, _ := promises.New(f.vu) go func() { @@ -188,7 +188,7 @@ func (f *File) Stat() *goja.Promise { // // It is possible for a read to successfully return with 0 bytes. // This does not indicate EOF. -func (f *File) Read(into goja.Value) *goja.Promise { +func (f *File) Read(into sobek.Value) *sobek.Promise { promise, resolve, reject := f.vu.Runtime().NewPromise() if common.IsNullish(into) { @@ -203,7 +203,7 @@ func (f *File) Read(into goja.Value) *goja.Promise { } // Obtain the underlying ArrayBuffer from the Uint8Array - ab, ok := intoObj.Get("buffer").Export().(goja.ArrayBuffer) + ab, ok := intoObj.Get("buffer").Export().(sobek.ArrayBuffer) if !ok { reject(newFsError(TypeError, "read() failed; reason: into argument must be a Uint8Array")) return promise @@ -240,7 +240,7 @@ func (f *File) Read(into goja.Value) *goja.Promise { } if fsErr.kind == EOFError && n == 0 { - resolve(goja.Null()) + resolve(sobek.Null()) } else { resolve(n) } @@ -257,7 +257,7 @@ func (f *File) Read(into goja.Value) *goja.Promise { // The returned promise resolves to the new `offset` (position) within the file, which // is expressed in bytes from the selected start, current, or end position depending // the provided `whence`. -func (f *File) Seek(offset goja.Value, whence goja.Value) *goja.Promise { +func (f *File) Seek(offset sobek.Value, whence sobek.Value) *sobek.Promise { promise, resolve, reject := f.vu.Runtime().NewPromise() intOffset, err := exportInt(offset) @@ -298,7 +298,7 @@ func (f *File) Seek(offset goja.Value, whence goja.Value) *goja.Promise { return promise } -func isUint8Array(rt *goja.Runtime, o *goja.Object) bool { +func isUint8Array(rt *sobek.Runtime, o *sobek.Object) bool { uint8ArrayConstructor := rt.Get("Uint8Array") if isUint8Array := o.Get("constructor").SameAs(uint8ArrayConstructor); !isUint8Array { return false @@ -307,7 +307,7 @@ func isUint8Array(rt *goja.Runtime, o *goja.Object) bool { return true } -func exportInt(v goja.Value) (int64, error) { +func exportInt(v sobek.Value) (int64, error) { if common.IsNullish(v) { return 0, errors.New("cannot be null or undefined") } diff --git a/js/modules/k6/experimental/streams/errors.go b/js/modules/k6/experimental/streams/errors.go index 09796e53275..cb038939b7a 100644 --- a/js/modules/k6/experimental/streams/errors.go +++ b/js/modules/k6/experimental/streams/errors.go @@ -1,17 +1,17 @@ package streams -import "github.com/dop251/goja" +import "github.com/grafana/sobek" -func newTypeError(rt *goja.Runtime, message string) *jsError { +func newTypeError(rt *sobek.Runtime, message string) *jsError { return newJsError(rt, rt.Get("TypeError"), TypeError, message) } -func newRangeError(rt *goja.Runtime, message string) *jsError { +func newRangeError(rt *sobek.Runtime, message string) *jsError { return newJsError(rt, rt.Get("RangeError"), RangeError, message) } -func newJsError(rt *goja.Runtime, base goja.Value, kind errorKind, message string) *jsError { - constructor, ok := goja.AssertConstructor(base) +func newJsError(rt *sobek.Runtime, base sobek.Value, kind errorKind, message string) *jsError { + constructor, ok := sobek.AssertConstructor(base) if !ok { throw(rt, newError(kind, message)) } @@ -28,9 +28,9 @@ func newJsError(rt *goja.Runtime, base goja.Value, kind errorKind, message strin // // We need to use it because whenever we need to return a [TypeError] // or a [RangeError], we want to use original JS errors, which can be -// retrieved from Goja, for instance with: goja.Runtime.Get("TypeError"). +// retrieved from Goja, for instance with: sobek.Runtime.Get("TypeError"). // -// However, that is implemented as a [*goja.Object], but sometimes we +// However, that is implemented as a [*sobek.Object], but sometimes we // need to return that error as a Go [error], or even keep the instance // in memory to be returned/thrown later. // @@ -38,7 +38,7 @@ func newJsError(rt *goja.Runtime, base goja.Value, kind errorKind, message strin // Otherwise, we would need to replace everything typed as [error] with // [any] to be compatible, and that would be a mess. type jsError struct { - err *goja.Object + err *sobek.Object msg string } @@ -46,7 +46,7 @@ func (e *jsError) Error() string { return e.msg } -func (e *jsError) Err() *goja.Object { +func (e *jsError) Err() *sobek.Object { return e.err } @@ -97,7 +97,7 @@ func (e *streamError) Error() string { return e.Name + ":" + e.Message } -func throw(rt *goja.Runtime, err any) { +func throw(rt *sobek.Runtime, err any) { if e, ok := err.(*jsError); ok { panic(e.Err()) } @@ -105,13 +105,13 @@ func throw(rt *goja.Runtime, err any) { panic(errToObj(rt, err)) } -func errToObj(rt *goja.Runtime, err any) goja.Value { +func errToObj(rt *sobek.Runtime, err any) sobek.Value { // Undefined remains undefined. - if goja.IsUndefined(rt.ToValue(err)) { + if sobek.IsUndefined(rt.ToValue(err)) { return rt.ToValue(err) } - if e, ok := err.(*goja.Exception); ok { + if e, ok := err.(*sobek.Exception); ok { return e.Value().ToObject(rt) } diff --git a/js/modules/k6/experimental/streams/goja.go b/js/modules/k6/experimental/streams/goja.go index ebcda31343b..e9b3a04e75a 100644 --- a/js/modules/k6/experimental/streams/goja.go +++ b/js/modules/k6/experimental/streams/goja.go @@ -4,20 +4,20 @@ import ( "fmt" "reflect" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) // newResolvedPromise instantiates a new resolved promise. -func newResolvedPromise(vu modules.VU, with goja.Value) *goja.Promise { +func newResolvedPromise(vu modules.VU, with sobek.Value) *sobek.Promise { promise, resolve, _ := vu.Runtime().NewPromise() resolve(with) return promise } // newRejectedPromise instantiates a new rejected promise. -func newRejectedPromise(vu modules.VU, with any) *goja.Promise { +func newRejectedPromise(vu modules.VU, with any) *sobek.Promise { promise, _, reject := vu.Runtime().NewPromise() reject(with) return promise @@ -26,32 +26,32 @@ func newRejectedPromise(vu modules.VU, with any) *goja.Promise { // promiseThen facilitates instantiating a new promise and defining callbacks for to be executed // on fulfillment as well as rejection, directly from Go. func promiseThen( - rt *goja.Runtime, - promise *goja.Promise, - onFulfilled, onRejected func(goja.Value), -) (*goja.Promise, error) { + rt *sobek.Runtime, + promise *sobek.Promise, + onFulfilled, onRejected func(sobek.Value), +) (*sobek.Promise, error) { val, err := rt.RunString( `(function(promise, onFulfilled, onRejected) { return promise.then(onFulfilled, onRejected) })`) if err != nil { return nil, newError(RuntimeError, "unable to initialize promiseThen internal helper function") } - cal, ok := goja.AssertFunction(val) + cal, ok := sobek.AssertFunction(val) if !ok { return nil, newError(RuntimeError, "the internal promiseThen helper is not a function") } if onRejected == nil { - val, err = cal(goja.Undefined(), rt.ToValue(promise), rt.ToValue(onFulfilled)) + val, err = cal(sobek.Undefined(), rt.ToValue(promise), rt.ToValue(onFulfilled)) } else { - val, err = cal(goja.Undefined(), rt.ToValue(promise), rt.ToValue(onFulfilled), rt.ToValue(onRejected)) + val, err = cal(sobek.Undefined(), rt.ToValue(promise), rt.ToValue(onFulfilled), rt.ToValue(onRejected)) } if err != nil { return nil, err } - newPromise, ok := val.Export().(*goja.Promise) + newPromise, ok := val.Export().(*sobek.Promise) if !ok { return nil, newError(RuntimeError, "unable to cast the internal promiseThen helper's return value to a promise") } @@ -60,7 +60,7 @@ func promiseThen( } // isNumber returns true if the given goja value holds a number -func isNumber(value goja.Value) bool { +func isNumber(value sobek.Value) bool { _, isFloat := value.Export().(float64) _, isInt := value.Export().(int64) @@ -70,7 +70,7 @@ func isNumber(value goja.Value) bool { // isNonNegativeNumber implements the [IsNonNegativeNumber] algorithm. // // [IsNonNegativeNumber]: https://streams.spec.whatwg.org/#is-non-negative-number -func isNonNegativeNumber(value goja.Value) bool { +func isNonNegativeNumber(value sobek.Value) bool { if common.IsNullish(value) { return false } @@ -86,13 +86,13 @@ func isNonNegativeNumber(value goja.Value) bool { return true } -// setReadOnlyPropertyOf sets a read-only property on the given [goja.Object]. -func setReadOnlyPropertyOf(obj *goja.Object, objName, propName string, propValue goja.Value) error { +// setReadOnlyPropertyOf sets a read-only property on the given [sobek.Object]. +func setReadOnlyPropertyOf(obj *sobek.Object, objName, propName string, propValue sobek.Value) error { err := obj.DefineDataProperty(propName, propValue, - goja.FLAG_FALSE, - goja.FLAG_FALSE, - goja.FLAG_TRUE, + sobek.FLAG_FALSE, + sobek.FLAG_FALSE, + sobek.FLAG_TRUE, ) if err != nil { return fmt.Errorf("unable to define %s read-only property on %s object; reason: %w", propName, objName, err) @@ -101,7 +101,7 @@ func setReadOnlyPropertyOf(obj *goja.Object, objName, propName string, propValue return nil } -// isObject determines whether the given [goja.Value] is a [goja.Object] or not. -func isObject(val goja.Value) bool { +// isObject determines whether the given [sobek.Value] is a [sobek.Object] or not. +func isObject(val sobek.Value) bool { return val != nil && val.ExportType() != nil && val.ExportType().Kind() == reflect.Map } diff --git a/js/modules/k6/experimental/streams/module.go b/js/modules/k6/experimental/streams/module.go index 51018a5ea79..caf52341fb6 100644 --- a/js/modules/k6/experimental/streams/module.go +++ b/js/modules/k6/experimental/streams/module.go @@ -2,7 +2,7 @@ package streams import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) @@ -45,15 +45,15 @@ func (mi *ModuleInstance) Exports() modules.Exports { } // NewReadableStream is the constructor for the ReadableStream object. -func (mi *ModuleInstance) NewReadableStream(call goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) NewReadableStream(call sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() var err error // 1. If underlyingSource is missing, set it to null. - var underlyingSource *goja.Object + var underlyingSource *sobek.Object var ( - strategy *goja.Object + strategy *sobek.Object underlyingSourceDict UnderlyingSource ) @@ -63,7 +63,7 @@ func (mi *ModuleInstance) NewReadableStream(call goja.ConstructorCall) *goja.Obj strategy = mi.initializeStrategy(call) // 2. Let underlyingSourceDict be underlyingSource, converted to an IDL value of type UnderlyingSource. - if len(call.Arguments) > 0 && !goja.IsUndefined(call.Arguments[0]) { + if len(call.Arguments) > 0 && !sobek.IsUndefined(call.Arguments[0]) { // We first assert that it is an object (requirement) if !isObject(call.Arguments[0]) { throw(rt, newTypeError(rt, "underlyingSource must be an object")) @@ -112,9 +112,9 @@ func (mi *ModuleInstance) NewReadableStream(call goja.ConstructorCall) *goja.Obj proto := call.This.Prototype() if proto.Get("locked") == nil { - err = proto.DefineAccessorProperty("locked", rt.ToValue(func() goja.Value { + err = proto.DefineAccessorProperty("locked", rt.ToValue(func() sobek.Value { return rt.ToValue(stream.Locked) - }), nil, goja.FLAG_FALSE, goja.FLAG_TRUE) + }), nil, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { common.Throw(rt, newError(RuntimeError, err.Error())) } @@ -127,9 +127,9 @@ func (mi *ModuleInstance) NewReadableStream(call goja.ConstructorCall) *goja.Obj return streamObj } -func defaultSizeFunc(_ goja.Value) (float64, error) { return 1.0, nil } +func defaultSizeFunc(_ sobek.Value) (float64, error) { return 1.0, nil } -func (mi *ModuleInstance) initializeStrategy(call goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) initializeStrategy(call sobek.ConstructorCall) *sobek.Object { runtime := mi.vu.Runtime() // Either if the strategy is not provided or if it doesn't have a 'highWaterMark', @@ -159,14 +159,14 @@ func (mi *ModuleInstance) initializeStrategy(call goja.ConstructorCall) *goja.Ob size = strArg.Get("size") } - strCall := goja.ConstructorCall{Arguments: []goja.Value{strArg}} + strCall := sobek.ConstructorCall{Arguments: []sobek.Value{strArg}} return mi.newCountQueuingStrategy(runtime, strCall, size) } // NewCountQueuingStrategy is the constructor for the [CountQueuingStrategy] object. // // [CountQueuingStrategy]: https://streams.spec.whatwg.org/#cqs-class -func (mi *ModuleInstance) NewCountQueuingStrategy(call goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) NewCountQueuingStrategy(call sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() // By default, the CountQueuingStrategy has a pre-defined 'size' property. // It cannot be overwritten by the user. @@ -178,10 +178,10 @@ func (mi *ModuleInstance) NewCountQueuingStrategy(call goja.ConstructorCall) *go // It allows to create a CountQueuingStrategy with or without the 'size' property, // depending on how the containing ReadableStream is initialized. func (mi *ModuleInstance) newCountQueuingStrategy( - rt *goja.Runtime, - call goja.ConstructorCall, - size goja.Value, -) *goja.Object { + rt *sobek.Runtime, + call sobek.ConstructorCall, + size sobek.Value, +) *sobek.Object { obj := rt.NewObject() objName := "CountQueuingStrategy" @@ -217,7 +217,7 @@ func (mi *ModuleInstance) newCountQueuingStrategy( // It implements the [ExtractHighWaterMark] algorithm. // // [ExtractHighWaterMark]: https://streams.spec.whatwg.org/#validate-and-normalize-high-water-mark -func extractHighWaterMark(rt *goja.Runtime, strategy *goja.Object, defaultHWM float64) float64 { +func extractHighWaterMark(rt *sobek.Runtime, strategy *sobek.Object, defaultHWM float64) float64 { // 1. If strategy["highWaterMark"] does not exist, return defaultHWM. if common.IsNullish(strategy.Get("highWaterMark")) { return defaultHWM @@ -227,7 +227,7 @@ func extractHighWaterMark(rt *goja.Runtime, strategy *goja.Object, defaultHWM fl highWaterMark := strategy.Get("highWaterMark") // 3. If highWaterMark is NaN or highWaterMark < 0, throw a RangeError exception. - if goja.IsNaN(strategy.Get("highWaterMark")) || + if sobek.IsNaN(strategy.Get("highWaterMark")) || !isNumber(strategy.Get("highWaterMark")) || !isNonNegativeNumber(strategy.Get("highWaterMark")) { throw(rt, newRangeError(rt, "highWaterMark must be a non-negative number")) @@ -242,16 +242,16 @@ func extractHighWaterMark(rt *goja.Runtime, strategy *goja.Object, defaultHWM fl // It implements the [ExtractSizeAlgorithm] algorithm. // // [ExtractSizeAlgorithm]: https://streams.spec.whatwg.org/#make-size-algorithm-from-size-function -func extractSizeAlgorithm(rt *goja.Runtime, strategy *goja.Object) SizeAlgorithm { - var sizeFunc goja.Callable +func extractSizeAlgorithm(rt *sobek.Runtime, strategy *sobek.Object) SizeAlgorithm { + var sizeFunc sobek.Callable sizeProp := strategy.Get("size") if common.IsNullish(sizeProp) { - sizeFunc, _ = goja.AssertFunction(rt.ToValue(func(_ goja.Value) (float64, error) { return 1.0, nil })) + sizeFunc, _ = sobek.AssertFunction(rt.ToValue(func(_ sobek.Value) (float64, error) { return 1.0, nil })) return sizeFunc } - sizeFunc, isFunc := goja.AssertFunction(sizeProp) + sizeFunc, isFunc := sobek.AssertFunction(sizeProp) if !isFunc { throw(rt, newTypeError(rt, "size must be a function")) } @@ -262,7 +262,7 @@ func extractSizeAlgorithm(rt *goja.Runtime, strategy *goja.Object) SizeAlgorithm // NewReadableStreamDefaultReader is the constructor for the [ReadableStreamDefaultReader] object. // // [ReadableStreamDefaultReader]: https://streams.spec.whatwg.org/#readablestreamdefaultreader -func (mi *ModuleInstance) NewReadableStreamDefaultReader(call goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) NewReadableStreamDefaultReader(call sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() if len(call.Arguments) != 1 { diff --git a/js/modules/k6/experimental/streams/queue.go b/js/modules/k6/experimental/streams/queue.go index c3e8bdb1aa7..cf73b66fb56 100644 --- a/js/modules/k6/experimental/streams/queue.go +++ b/js/modules/k6/experimental/streams/queue.go @@ -4,14 +4,14 @@ import ( "errors" "math" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) // ValueWithSize holds a value and its corresponding size. // // It is used to store values in the queue. type ValueWithSize struct { - Value goja.Value + Value sobek.Value Size float64 } @@ -19,13 +19,13 @@ type ValueWithSize struct { type QueueWithSizes struct { Queue []ValueWithSize QueueTotalSize float64 - runtime *goja.Runtime + runtime *sobek.Runtime } // NewQueueWithSizes creates a new queue of values with sizes, as described in the [specification]. // // [specification]: https://streams.spec.whatwg.org/#queue-with-sizes -func NewQueueWithSizes(runtime *goja.Runtime) *QueueWithSizes { +func NewQueueWithSizes(runtime *sobek.Runtime) *QueueWithSizes { return &QueueWithSizes{ Queue: make([]ValueWithSize, 0), runtime: runtime, @@ -35,7 +35,7 @@ func NewQueueWithSizes(runtime *goja.Runtime) *QueueWithSizes { // Enqueue adds a value to the queue, and implements the specification's [EnqueueValueWithSize] abstract operation. // // [EnqueueValueWithSize]: https://streams.spec.whatwg.org/#enqueue-value-with-size -func (q *QueueWithSizes) Enqueue(value goja.Value, size float64) error { +func (q *QueueWithSizes) Enqueue(value sobek.Value, size float64) error { if math.IsNaN(size) || size < 0 || math.IsInf(size, 1) { // Check for +Inf return newRangeError(q.runtime, "size must be a finite, non-NaN number") } @@ -56,7 +56,7 @@ func (q *QueueWithSizes) Enqueue(value goja.Value, size float64) error { // It implements the [DequeueValue] abstract operation. // // [DequeueValue]: https://streams.spec.whatwg.org/#abstract-opdef-dequeue-value -func (q *QueueWithSizes) Dequeue() (goja.Value, error) { +func (q *QueueWithSizes) Dequeue() (sobek.Value, error) { if len(q.Queue) == 0 { return nil, newError(AssertionError, "queue is empty") } @@ -76,7 +76,7 @@ func (q *QueueWithSizes) Dequeue() (goja.Value, error) { // It implements the [PeekQueueValue] abstract operation. // // [PeekQueueValue]: https://streams.spec.whatwg.org/#abstract-opdef-peek-queue-value -func (q *QueueWithSizes) Peek() (goja.Value, error) { +func (q *QueueWithSizes) Peek() (sobek.Value, error) { if len(q.Queue) == 0 { return nil, errors.New("queue is empty") } diff --git a/js/modules/k6/experimental/streams/readable_stream_controller.go b/js/modules/k6/experimental/streams/readable_stream_controller.go index d0e7869085f..1c5bfbb7914 100644 --- a/js/modules/k6/experimental/streams/readable_stream_controller.go +++ b/js/modules/k6/experimental/streams/readable_stream_controller.go @@ -1,19 +1,19 @@ package streams -import "github.com/dop251/goja" +import "github.com/grafana/sobek" // ReadableStreamController is the interface implemented by all readable stream controllers. // // It defines both the specification's shared controller and private methods. type ReadableStreamController interface { Close() - Enqueue(chunk goja.Value) - Error(err goja.Value) + Enqueue(chunk sobek.Value) + Error(err sobek.Value) // cancelSteps performs the controller’s steps that run in reaction to // the stream being canceled, used to clean up the state stored in the // controller and inform the underlying source. - cancelSteps(reason any) *goja.Promise + cancelSteps(reason any) *sobek.Promise // pullSteps performs the controller’s steps that run when a default reader // is read from, used to pull from the controller any queued chunks, or @@ -24,10 +24,10 @@ type ReadableStreamController interface { // released, used to clean up reader-specific resources stored in the controller. releaseSteps() - // toObject returns a [*goja.Object] that represents the controller. - toObject() (*goja.Object, error) + // toObject returns a [*sobek.Object] that represents the controller. + toObject() (*sobek.Object, error) } // SizeAlgorithm is a function that returns the size of a chunk. -// type SizeAlgorithm func(chunk goja.Value) (float64, error) -type SizeAlgorithm = goja.Callable +// type SizeAlgorithm func(chunk sobek.Value) (float64, error) +type SizeAlgorithm = sobek.Callable diff --git a/js/modules/k6/experimental/streams/readable_stream_default_controller.go b/js/modules/k6/experimental/streams/readable_stream_default_controller.go index ebc531317f9..cf36b966d03 100644 --- a/js/modules/k6/experimental/streams/readable_stream_default_controller.go +++ b/js/modules/k6/experimental/streams/readable_stream_default_controller.go @@ -1,7 +1,7 @@ package streams import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "gopkg.in/guregu/null.v3" ) @@ -56,26 +56,26 @@ type ReadableStreamDefaultController struct { // Ensure that ReadableStreamDefaultController implements the ReadableStreamController interface. var _ ReadableStreamController = &ReadableStreamDefaultController{} -// NewReadableStreamDefaultControllerObject creates a new [goja.Object] from a +// NewReadableStreamDefaultControllerObject creates a new [sobek.Object] from a // [ReadableStreamDefaultController] instance. -func NewReadableStreamDefaultControllerObject(controller *ReadableStreamDefaultController) (*goja.Object, error) { +func NewReadableStreamDefaultControllerObject(controller *ReadableStreamDefaultController) (*sobek.Object, error) { rt := controller.stream.runtime obj := rt.NewObject() objName := "ReadableStreamDefaultController" - err := obj.DefineAccessorProperty("desiredSize", rt.ToValue(func() goja.Value { + err := obj.DefineAccessorProperty("desiredSize", rt.ToValue(func() sobek.Value { desiredSize := controller.getDesiredSize() if !desiredSize.Valid { - return goja.Null() + return sobek.Null() } return rt.ToValue(desiredSize.Float64) - }), nil, goja.FLAG_FALSE, goja.FLAG_TRUE) + }), nil, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { return nil, err } // Exposing the properties of the [ReadableStreamController] interface - if err := setReadOnlyPropertyOf(obj, objName, "constructor", rt.ToValue(func() goja.Value { + if err := setReadOnlyPropertyOf(obj, objName, "constructor", rt.ToValue(func() sobek.Value { return rt.ToValue(&ReadableStreamDefaultController{}) })); err != nil { return nil, err @@ -118,7 +118,7 @@ func (controller *ReadableStreamDefaultController) Close() { // It implements the ReadableStreamDefaultController.enqueue(chunk) [specification] algorithm. // // [specification]: https://streams.spec.whatwg.org/#rs-default-controller-enqueue -func (controller *ReadableStreamDefaultController) Enqueue(chunk goja.Value) { +func (controller *ReadableStreamDefaultController) Enqueue(chunk sobek.Value) { rt := controller.stream.vu.Runtime() // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(this) is false, throw a TypeError exception. @@ -138,9 +138,9 @@ func (controller *ReadableStreamDefaultController) Enqueue(chunk goja.Value) { // It implements the ReadableStreamDefaultController.error(e) [specification] algorithm. // // [specification]: https://streams.spec.whatwg.org/#rs-default-controller-error -func (controller *ReadableStreamDefaultController) Error(err goja.Value) { +func (controller *ReadableStreamDefaultController) Error(err sobek.Value) { if err == nil { - err = goja.Undefined() + err = sobek.Undefined() } controller.error(err) } @@ -153,7 +153,7 @@ func (controller *ReadableStreamDefaultController) Error(err goja.Value) { // algorithm. // // [specification]: https://streams.spec.whatwg.org/#readable-stream-default-controller-cancel-steps -func (controller *ReadableStreamDefaultController) cancelSteps(reason any) *goja.Promise { +func (controller *ReadableStreamDefaultController) cancelSteps(reason any) *sobek.Promise { // 1. Perform ! ResetQueue(this). controller.resetQueue() @@ -164,7 +164,7 @@ func (controller *ReadableStreamDefaultController) cancelSteps(reason any) *goja controller.clearAlgorithms() // 4. Return result. - if p, ok := result.Export().(*goja.Promise); ok { + if p, ok := result.Export().(*sobek.Promise); ok { return p } @@ -252,7 +252,7 @@ func (controller *ReadableStreamDefaultController) close() { // algorithm. // // [specification]: https://streams.spec.whatwg.org/#readable-stream-default-controller-enqueue -func (controller *ReadableStreamDefaultController) enqueue(chunk goja.Value) error { +func (controller *ReadableStreamDefaultController) enqueue(chunk sobek.Value) error { // 1. If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) is false, return. if !controller.canCloseOrEnqueue() { return nil @@ -268,7 +268,7 @@ func (controller *ReadableStreamDefaultController) enqueue(chunk goja.Value) err } else { // 4. Otherwise, // 4.1. Let result be the result of performing controller.[[strategySizeAlgorithm]], // passing in chunk, and interpreting the result as a completion record. - size, err := controller.strategySizeAlgorithm(goja.Undefined(), chunk) + size, err := controller.strategySizeAlgorithm(sobek.Undefined(), chunk) // 4.2 If result is an abrupt completion, if err != nil { // 4.2.1. Perform ! ReadableStreamDefaultControllerError(controller, result.[[Value]]). @@ -408,7 +408,7 @@ func (controller *ReadableStreamDefaultController) callPullIfNeeded() { _, err = promiseThen(controller.stream.vu.Runtime(), pullPromise, // 7. Upon fulfillment of pullPromise - func(goja.Value) { + func(sobek.Value) { // 7.1. Set controller.[[pulling]] to false. controller.pulling = false @@ -422,7 +422,7 @@ func (controller *ReadableStreamDefaultController) callPullIfNeeded() { }, // 8. Upon rejection of pullPromise with reason e, - func(reason goja.Value) { + func(reason sobek.Value) { // 8.1. Perform ! ReadableStreamDefaultControllerError(controller, e). controller.error(reason) }, @@ -485,6 +485,6 @@ func (controller *ReadableStreamDefaultController) getDesiredSize() null.Float { return null.NewFloat(controller.strategyHWM-controller.queue.QueueTotalSize, true) } -func (controller *ReadableStreamDefaultController) toObject() (*goja.Object, error) { +func (controller *ReadableStreamDefaultController) toObject() (*sobek.Object, error) { return NewReadableStreamDefaultControllerObject(controller) } diff --git a/js/modules/k6/experimental/streams/readable_stream_default_reader.go b/js/modules/k6/experimental/streams/readable_stream_default_reader.go index cb9184d9be2..12edf803e48 100644 --- a/js/modules/k6/experimental/streams/readable_stream_default_reader.go +++ b/js/modules/k6/experimental/streams/readable_stream_default_reader.go @@ -1,7 +1,7 @@ package streams import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" ) @@ -14,16 +14,16 @@ type ReadableStreamDefaultReader struct { readRequests []ReadRequest } -// NewReadableStreamDefaultReaderObject creates a new goja.Object from a [ReadableStreamDefaultReader] instance. -func NewReadableStreamDefaultReaderObject(reader *ReadableStreamDefaultReader) (*goja.Object, error) { +// NewReadableStreamDefaultReaderObject creates a new sobek.Object from a [ReadableStreamDefaultReader] instance. +func NewReadableStreamDefaultReaderObject(reader *ReadableStreamDefaultReader) (*sobek.Object, error) { rt := reader.stream.runtime obj := rt.NewObject() objName := "ReadableStreamDefaultReader" - err := obj.DefineAccessorProperty("closed", rt.ToValue(func() *goja.Promise { + err := obj.DefineAccessorProperty("closed", rt.ToValue(func() *sobek.Promise { p, _, _ := reader.GetClosed() return p - }), nil, goja.FLAG_FALSE, goja.FLAG_TRUE) + }), nil, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { return nil, err } @@ -47,8 +47,8 @@ func NewReadableStreamDefaultReaderObject(reader *ReadableStreamDefaultReader) ( // Ensure the ReadableStreamReader interface is implemented correctly var _ ReadableStreamReader = &ReadableStreamDefaultReader{} -// Read returns a [goja.Promise] providing access to the next chunk in the stream's internal queue. -func (reader *ReadableStreamDefaultReader) Read() *goja.Promise { +// Read returns a [sobek.Promise] providing access to the next chunk in the stream's internal queue. +func (reader *ReadableStreamDefaultReader) Read() *sobek.Promise { stream := reader.GetStream() // 1. If this.[[stream]] is undefined, return a promise rejected with a TypeError exception. @@ -67,7 +67,7 @@ func (reader *ReadableStreamDefaultReader) Read() *goja.Promise { }, closeSteps: func() { // Resolve promise with «[ "value" → undefined, "done" → true ]». - resolve(map[string]any{"value": goja.Undefined(), "done": true}) + resolve(map[string]any{"value": sobek.Undefined(), "done": true}) }, errorSteps: func(e any) { // Reject promise with e. @@ -82,7 +82,7 @@ func (reader *ReadableStreamDefaultReader) Read() *goja.Promise { return promise } -// Cancel returns a [goja.Promise] that resolves when the stream is canceled. +// Cancel returns a [sobek.Promise] that resolves when the stream is canceled. // // Calling this method signals a loss of interest in the stream by a consumer. The // supplied reason argument will be given to the underlying source, which may or @@ -92,7 +92,7 @@ func (reader *ReadableStreamDefaultReader) Read() *goja.Promise { // the cancellation. This value may or may not be used. // // [SetUpReadableStreamDefaultReader]: https://streams.spec.whatwg.org/#set-up-readable-stream-default-reader -func (reader *ReadableStreamDefaultReader) Cancel(reason goja.Value) *goja.Promise { +func (reader *ReadableStreamDefaultReader) Cancel(reason sobek.Value) *sobek.Promise { // 1. If this.[[stream]] is undefined, return a promise rejected with a TypeError exception. if reader.stream == nil { return newRejectedPromise(reader.vu, newTypeError(reader.runtime, "stream is undefined").Err()) @@ -107,7 +107,7 @@ func (reader *ReadableStreamDefaultReader) Cancel(reason goja.Value) *goja.Promi // It contains the value read from the stream and a boolean indicating whether or not the stream is done. // An undefined value indicates that the stream has been closed. type ReadResult struct { - Value goja.Value + Value sobek.Value Done bool } diff --git a/js/modules/k6/experimental/streams/readable_stream_reader.go b/js/modules/k6/experimental/streams/readable_stream_reader.go index d2e5df9101f..a706cba7a23 100644 --- a/js/modules/k6/experimental/streams/readable_stream_reader.go +++ b/js/modules/k6/experimental/streams/readable_stream_reader.go @@ -1,7 +1,7 @@ package streams import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) @@ -10,8 +10,8 @@ import ( type ReadableStreamReader interface { ReadableStreamGenericReader - // Read returns a [goja.Promise] providing access to the next chunk in the stream's internal queue. - Read() *goja.Promise + // Read returns a [sobek.Promise] providing access to the next chunk in the stream's internal queue. + Read() *sobek.Promise // ReleaseLock releases the reader's lock on the stream. ReleaseLock() @@ -34,26 +34,26 @@ type ReadableStreamGenericReader interface { // SetStream sets the stream that owns this reader. SetStream(stream *ReadableStream) - // GetClosed returns a [goja.Promise] that resolves when the stream is closed. - GetClosed() (p *goja.Promise, resolve func(any), reject func(any)) + // GetClosed returns a [sobek.Promise] that resolves when the stream is closed. + GetClosed() (p *sobek.Promise, resolve func(any), reject func(any)) - // SetClosed sets the [goja.Promise] that resolves when the stream is closed. - SetClosed(p *goja.Promise, resolve func(any), reject func(any)) + // SetClosed sets the [sobek.Promise] that resolves when the stream is closed. + SetClosed(p *sobek.Promise, resolve func(any), reject func(any)) - // Cancel returns a [goja.Promise] that resolves when the stream is canceled. - Cancel(reason goja.Value) *goja.Promise + // Cancel returns a [sobek.Promise] that resolves when the stream is canceled. + Cancel(reason sobek.Value) *sobek.Promise } // BaseReadableStreamReader is a base implement type BaseReadableStreamReader struct { - closedPromise *goja.Promise + closedPromise *sobek.Promise closedPromiseResolveFunc func(resolve any) closedPromiseRejectFunc func(reason any) // stream is a [ReadableStream] instance that owns this reader stream *ReadableStream - runtime *goja.Runtime + runtime *sobek.Runtime vu modules.VU } @@ -73,26 +73,26 @@ func (reader *BaseReadableStreamReader) SetStream(stream *ReadableStream) { } // GetClosed returns the reader's closed promise as well as its resolve and reject functions. -func (reader *BaseReadableStreamReader) GetClosed() (p *goja.Promise, resolve func(any), reject func(any)) { +func (reader *BaseReadableStreamReader) GetClosed() (p *sobek.Promise, resolve func(any), reject func(any)) { return reader.closedPromise, reader.closedPromiseResolveFunc, reader.closedPromiseRejectFunc } // SetClosed sets the reader's closed promise as well as its resolve and reject functions. -func (reader *BaseReadableStreamReader) SetClosed(p *goja.Promise, resolve func(any), reject func(any)) { +func (reader *BaseReadableStreamReader) SetClosed(p *sobek.Promise, resolve func(any), reject func(any)) { reader.closedPromise = p reader.closedPromiseResolveFunc = resolve reader.closedPromiseRejectFunc = reject } -// Cancel returns a [goja.Promise] that resolves when the stream is canceled. -func (reader *BaseReadableStreamReader) Cancel(reason goja.Value) *goja.Promise { +// Cancel returns a [sobek.Promise] that resolves when the stream is canceled. +func (reader *BaseReadableStreamReader) Cancel(reason sobek.Value) *sobek.Promise { return reader.cancel(reason) } // cancel implements the [ReadableStreamReaderGenericCancel(reader, reason)] [specification] algorithm. // // [specification]: https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel -func (reader *BaseReadableStreamReader) cancel(reason goja.Value) *goja.Promise { +func (reader *BaseReadableStreamReader) cancel(reason sobek.Value) *sobek.Promise { // 1. Let stream be reader.[[stream]]. stream := reader.stream @@ -142,7 +142,7 @@ func (reader *BaseReadableStreamReader) release() { // FIXME: See https://github.com/dop251/goja/issues/565 var ( err error - doNothing = func(goja.Value) {} + doNothing = func(sobek.Value) {} ) _, err = promiseThen(stream.vu.Runtime(), reader.closedPromise, doNothing, doNothing) if err != nil { @@ -196,7 +196,7 @@ func ReadableStreamReaderGenericInitialize(reader ReadableStreamGenericReader, s // 4. Otherwise, if stream.[[state]] is "closed", case ReadableStreamStateClosed: // 4.1 Set reader.[[closedPromise]] to a promise resolved with undefined. - resolve(goja.Undefined()) + resolve(sobek.Undefined()) // 5. Otherwise, default: // 5.1 Assert: stream.[[state]] is "errored". @@ -215,7 +215,7 @@ func ReadableStreamReaderGenericInitialize(reader ReadableStreamGenericReader, s // See https://github.com/dop251/goja/issues/565 var ( err error - doNothing = func(goja.Value) {} + doNothing = func(sobek.Value) {} ) _, err = promiseThen(stream.vu.Runtime(), promise, doNothing, doNothing) if err != nil { diff --git a/js/modules/k6/experimental/streams/readable_streams.go b/js/modules/k6/experimental/streams/readable_streams.go index c26d6b8d2c8..2c00e4d671d 100644 --- a/js/modules/k6/experimental/streams/readable_streams.go +++ b/js/modules/k6/experimental/streams/readable_streams.go @@ -3,7 +3,7 @@ package streams import ( "errors" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/js/promises" @@ -36,14 +36,14 @@ type ReadableStream struct { // storedError holds the error that caused the stream to be errored storedError any - Source *goja.Object + Source *sobek.Object - runtime *goja.Runtime + runtime *sobek.Runtime vu modules.VU } // Cancel cancels the stream and returns a Promise to the user -func (stream *ReadableStream) Cancel(reason goja.Value) *goja.Promise { +func (stream *ReadableStream) Cancel(reason sobek.Value) *sobek.Promise { // 1. IsReadableStreamLocked(this) is true, return a promise rejected with a TypeError exception. if stream.isLocked() { promise, _, reject := promises.New(stream.vu) @@ -62,9 +62,10 @@ func (stream *ReadableStream) Cancel(reason goja.Value) *goja.Promise { // GetReader implements the [getReader] operation. // // [getReader]: https://streams.spec.whatwg.org/#rs-get-reader -func (stream *ReadableStream) GetReader(options *goja.Object) goja.Value { +func (stream *ReadableStream) GetReader(options *sobek.Object) sobek.Value { // 1. If options["mode"] does not exist, return ? AcquireReadableStreamDefaultReader(this). - if options == nil || common.IsNullish(options) || options.Get("mode") == nil || goja.IsUndefined(options.Get("mode")) { + if options == nil || common.IsNullish(options) || + options.Get("mode") == nil || sobek.IsUndefined(options.Get("mode")) { defaultReader := stream.acquireDefaultReader() defaultReaderObj, err := NewReadableStreamDefaultReaderObject(defaultReader) if err != nil { @@ -81,15 +82,15 @@ func (stream *ReadableStream) GetReader(options *goja.Object) goja.Value { // 3. Return ? AcquireReadableStreamBYOBReader(this). common.Throw(stream.runtime, newError(NotSupportedError, "'byob' mode is not supported yet")) - return goja.Undefined() + return sobek.Undefined() } // Tee implements the [tee] operation. // // [tee]: https://streams.spec.whatwg.org/#rs-tee -func (stream *ReadableStream) Tee() goja.Value { +func (stream *ReadableStream) Tee() sobek.Value { common.Throw(stream.runtime, newError(NotSupportedError, "'tee()' is not supported yet")) - return goja.Undefined() + return sobek.Undefined() } // ReadableStreamState represents the current state of a ReadableStream @@ -137,7 +138,7 @@ func (stream *ReadableStream) initialize() { // // [specification]: https://streams.spec.whatwg.org/#set-up-readable-stream-default-controller-from-underlying-source func (stream *ReadableStream) setupReadableStreamDefaultControllerFromUnderlyingSource( - underlyingSource *goja.Object, + underlyingSource *sobek.Object, underlyingSourceDict UnderlyingSource, highWaterMark float64, sizeAlgorithm SizeAlgorithm, @@ -146,18 +147,18 @@ func (stream *ReadableStream) setupReadableStreamDefaultControllerFromUnderlying controller := &ReadableStreamDefaultController{} // 2. Let startAlgorithm be an algorithm that returns undefined. - var startAlgorithm UnderlyingSourceStartCallback = func(*goja.Object) goja.Value { - return goja.Undefined() + var startAlgorithm UnderlyingSourceStartCallback = func(*sobek.Object) sobek.Value { + return sobek.Undefined() } // 3. Let pullAlgorithm be an algorithm that returns a promise resolved with undefined. - var pullAlgorithm UnderlyingSourcePullCallback = func(*goja.Object) *goja.Promise { - return newResolvedPromise(stream.vu, goja.Undefined()) + var pullAlgorithm UnderlyingSourcePullCallback = func(*sobek.Object) *sobek.Promise { + return newResolvedPromise(stream.vu, sobek.Undefined()) } // 4. Let cancelAlgorithm be an algorithm that returns a promise resolved with undefined. - var cancelAlgorithm UnderlyingSourceCancelCallback = func(any) goja.Value { - return stream.vu.Runtime().ToValue(newResolvedPromise(stream.vu, goja.Undefined())) + var cancelAlgorithm UnderlyingSourceCancelCallback = func(any) sobek.Value { + return stream.vu.Runtime().ToValue(newResolvedPromise(stream.vu, sobek.Undefined())) } // 5. If underlyingSourceDict["start"] exists, then set startAlgorithm to an algorithm @@ -186,15 +187,15 @@ func (stream *ReadableStream) setupReadableStreamDefaultControllerFromUnderlying } func (stream *ReadableStream) startAlgorithm( - underlyingSource *goja.Object, + underlyingSource *sobek.Object, underlyingSourceDict UnderlyingSource, ) UnderlyingSourceStartCallback { - call, ok := goja.AssertFunction(underlyingSourceDict.Start) + call, ok := sobek.AssertFunction(underlyingSourceDict.Start) if !ok { throw(stream.runtime, newTypeError(stream.runtime, "underlyingSource.[[start]] must be a function")) } - return func(obj *goja.Object) (v goja.Value) { + return func(obj *sobek.Object) (v sobek.Value) { var err error v, err = call(underlyingSource, obj) if err != nil { @@ -206,25 +207,25 @@ func (stream *ReadableStream) startAlgorithm( } func (stream *ReadableStream) pullAlgorithm( - underlyingSource *goja.Object, + underlyingSource *sobek.Object, underlyingSourceDict UnderlyingSource, ) UnderlyingSourcePullCallback { - call, ok := goja.AssertFunction(underlyingSourceDict.Pull) + call, ok := sobek.AssertFunction(underlyingSourceDict.Pull) if !ok { throw(stream.runtime, newTypeError(stream.runtime, "underlyingSource.[[pull]] must be a function")) } - return func(obj *goja.Object) *goja.Promise { + return func(obj *sobek.Object) *sobek.Promise { v, err := call(underlyingSource, obj) if err != nil { - var ex *goja.Exception + var ex *sobek.Exception if errors.As(err, &ex) { return newRejectedPromise(stream.vu, ex.Value()) } return newRejectedPromise(stream.vu, err) } - if p, ok := v.Export().(*goja.Promise); ok { + if p, ok := v.Export().(*sobek.Promise); ok { return p } @@ -233,16 +234,16 @@ func (stream *ReadableStream) pullAlgorithm( } func (stream *ReadableStream) cancelAlgorithm( - underlyingSource *goja.Object, + underlyingSource *sobek.Object, underlyingSourceDict UnderlyingSource, ) UnderlyingSourceCancelCallback { - call, ok := goja.AssertFunction(underlyingSourceDict.Cancel) + call, ok := sobek.AssertFunction(underlyingSourceDict.Cancel) if !ok { throw(stream.runtime, newTypeError(stream.runtime, "underlyingSource.[[cancel]] must be a function")) } - return func(reason any) goja.Value { - var p *goja.Promise + return func(reason any) sobek.Value { + var p *sobek.Promise if e := stream.runtime.Try(func() { res, err := call(underlyingSource, stream.runtime.ToValue(reason)) @@ -250,7 +251,7 @@ func (stream *ReadableStream) cancelAlgorithm( panic(err) } - if cp, ok := res.Export().(*goja.Promise); ok { + if cp, ok := res.Export().(*sobek.Promise); ok { p = cp } }); e != nil { @@ -258,7 +259,7 @@ func (stream *ReadableStream) cancelAlgorithm( } if p == nil { - p = newResolvedPromise(stream.vu, goja.Undefined()) + p = newResolvedPromise(stream.vu, sobek.Undefined()) } return stream.vu.Runtime().ToValue(p) @@ -313,11 +314,11 @@ func (stream *ReadableStream) setupDefaultController( startResult := startAlgorithm(controllerObj) // 10. Let startPromise be a promise with startResult. - var startPromise *goja.Promise + var startPromise *sobek.Promise if common.IsNullish(startResult) { startPromise = newResolvedPromise(controller.stream.vu, startResult) - } else if p, ok := startResult.Export().(*goja.Promise); ok { - if p.State() == goja.PromiseStateRejected { + } else if p, ok := startResult.Export().(*sobek.Promise); ok { + if p.State() == sobek.PromiseStateRejected { controller.error(p.Result()) } startPromise = p @@ -326,7 +327,7 @@ func (stream *ReadableStream) setupDefaultController( } _, err = promiseThen(stream.vu.Runtime(), startPromise, // 11. Upon fulfillment of startPromise, - func(goja.Value) { + func(sobek.Value) { // 11.1. Set controller.[[started]] to true. controller.started = true // 11.2. Assert: controller.[[pulling]] is false. @@ -341,7 +342,7 @@ func (stream *ReadableStream) setupDefaultController( controller.callPullIfNeeded() }, // 12. Upon rejection of startPromise with reason r, - func(err goja.Value) { + func(err sobek.Value) { controller.error(err) }, ) @@ -388,13 +389,13 @@ func (stream *ReadableStream) addReadRequest(readRequest ReadRequest) { // cancel implements the specification's [ReadableStreamCancel()] abstract operation. // // [ReadableStreamCancel()]: https://streams.spec.whatwg.org/#readable-stream-cancel -func (stream *ReadableStream) cancel(reason goja.Value) *goja.Promise { +func (stream *ReadableStream) cancel(reason sobek.Value) *sobek.Promise { // 1. Set stream.[[disturbed]] to true. stream.disturbed = true // 2. If stream.[[state]] is "closed", return a promise resolved with undefined. if stream.state == ReadableStreamStateClosed { - return newResolvedPromise(stream.vu, goja.Undefined()) + return newResolvedPromise(stream.vu, sobek.Undefined()) } // 3. If stream.[[state]] is "errored", return a promise rejected with stream.[[storedError]]. @@ -418,8 +419,8 @@ func (stream *ReadableStream) cancel(reason goja.Value) *goja.Promise { // 8. Return the result of reacting to sourceCancelPromise with a fulfillment step that returns undefined. promise, err := promiseThen(stream.vu.Runtime(), sourceCancelPromise, // Mimicking Deno's implementation: https://github.com/denoland/deno/blob/main/ext/web/06_streams.js#L405 - func(goja.Value) {}, - func(err goja.Value) { throw(stream.vu.Runtime(), err) }, + func(sobek.Value) {}, + func(err sobek.Value) { throw(stream.vu.Runtime(), err) }, ) if err != nil { common.Throw(stream.vu.Runtime(), err) @@ -455,7 +456,7 @@ func (stream *ReadableStream) close() { } _, resolveFunc, _ := genericReader.GetClosed() - resolveFunc(goja.Undefined()) + resolveFunc(sobek.Undefined()) // 6. If reader implements ReadableStreamDefaultReader, defaultReader, ok := reader.(*ReadableStreamDefaultReader) @@ -513,7 +514,7 @@ func (stream *ReadableStream) error(e any) { // See https://github.com/dop251/goja/issues/565 var ( err error - doNothing = func(goja.Value) {} + doNothing = func(sobek.Value) {} ) _, err = promiseThen(stream.vu.Runtime(), promise, doNothing, doNothing) if err != nil { diff --git a/js/modules/k6/experimental/streams/underlying_source.go b/js/modules/k6/experimental/streams/underlying_source.go index 1ea84ea835d..b798a1e54bf 100644 --- a/js/modules/k6/experimental/streams/underlying_source.go +++ b/js/modules/k6/experimental/streams/underlying_source.go @@ -1,7 +1,7 @@ package streams import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "gopkg.in/guregu/null.v3" ) @@ -16,7 +16,7 @@ type UnderlyingSource struct { // Typically, this is used to a adapt a push source by setting up relevant event listeners. // If the setup process is asynchronous, it can return a Promise to signal success or // failure; a rejected promise will error the stream. - Start goja.Value `json:"start"` + Start sobek.Value `json:"start"` // PullFunc is a function that is called whenever the stream's internal queue of chunks // becomes not full, i.e. whenever the queue's desired size becomes positive. @@ -26,7 +26,7 @@ type UnderlyingSource struct { // This function will not be called until `start()` successfully completes. Additionally, // it will only be called repeatedly if it enqueues at least one chunk or fulfills a // BYOB request; a no-op `pull` implementation will not be continually called. - Pull goja.Value `json:"pull"` + Pull sobek.Value `json:"pull"` // CancelFunc is a function that is called when the stream's or reader's `cancel()` method is // called. @@ -38,7 +38,7 @@ type UnderlyingSource struct { // If the shutdown process is asynchronous, it can return a promise to signal success or // failure; the result will be communicated via the return value of the cancel() method // that was called. Throwing an exception is treated the same as returning a rejected promise. - Cancel goja.Value `json:"cancel"` + Cancel sobek.Value `json:"cancel"` // Type is a string indicating the type of the underlying source. Type ReadableStreamType `json:"type"` @@ -64,18 +64,18 @@ type UnderlyingSource struct { } // UnderlyingSourceStartCallback is a function that is called immediately during the creation of a ReadableStream. -type UnderlyingSourceStartCallback func(controller *goja.Object) goja.Value +type UnderlyingSourceStartCallback func(controller *sobek.Object) sobek.Value // UnderlyingSourcePullCallback is a function that is called whenever the stream's internal queue of chunks // becomes not full, i.e. whenever the queue's desired size becomes positive. -type UnderlyingSourcePullCallback func(controller *goja.Object) *goja.Promise +type UnderlyingSourcePullCallback func(controller *sobek.Object) *sobek.Promise // UnderlyingSourceCancelCallback is a function that is called when the stream's or reader's `cancel()` method is // called. -type UnderlyingSourceCancelCallback func(reason any) goja.Value +type UnderlyingSourceCancelCallback func(reason any) sobek.Value -// NewUnderlyingSourceFromObject creates a new UnderlyingSource from a goja.Object. -func NewUnderlyingSourceFromObject(rt *goja.Runtime, obj *goja.Object) (UnderlyingSource, error) { +// NewUnderlyingSourceFromObject creates a new UnderlyingSource from a sobek.Object. +func NewUnderlyingSourceFromObject(rt *sobek.Runtime, obj *sobek.Object) (UnderlyingSource, error) { var underlyingSource UnderlyingSource if common.IsNullish(obj) { @@ -86,7 +86,7 @@ func NewUnderlyingSourceFromObject(rt *goja.Runtime, obj *goja.Object) (Underlyi // We only accept a valid underlyingSource.[[type]] underlyingSourceType := obj.Get("type") if underlyingSourceType != nil && - !goja.IsUndefined(obj.Get("type")) && + !sobek.IsUndefined(obj.Get("type")) && obj.Get("type").String() != ReadableStreamTypeBytes { return underlyingSource, newTypeError(rt, "invalid underlying source type") } diff --git a/js/modules/k6/experimental/tracing/client.go b/js/modules/k6/experimental/tracing/client.go index 2b0696a7ffc..99f81cd92b7 100644 --- a/js/modules/k6/experimental/tracing/client.go +++ b/js/modules/k6/experimental/tracing/client.go @@ -6,7 +6,7 @@ import ( "net/http" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" httpmodule "go.k6.io/k6/js/modules/k6/http" @@ -46,11 +46,11 @@ type Client struct { type ( // HTTPRequestFunc is a type alias representing the prototype of // k6's http module's request function - HTTPRequestFunc func(method string, url goja.Value, args ...goja.Value) (*httpmodule.Response, error) + HTTPRequestFunc func(method string, url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) // HTTPAsyncRequestFunc is a type alias representing the prototype of // k6's http module's asyncRequest function - HTTPAsyncRequestFunc func(method string, url goja.Value, args ...goja.Value) (*goja.Promise, error) + HTTPAsyncRequestFunc func(method string, url sobek.Value, args ...sobek.Value) (*sobek.Promise, error) ) // NewClient instantiates a new tracing Client @@ -65,14 +65,14 @@ func NewClient(vu modules.VU, opts options) (*Client, error) { } httpModuleObject := httpModule.ToObject(rt) - // Export the http module's request function goja.Callable as a Go function + // Export the http module's request function sobek.Callable as a Go function var requestFunc HTTPRequestFunc if err := rt.ExportTo(httpModuleObject.Get("request"), &requestFunc); err != nil { return nil, fmt.Errorf("failed initializing tracing client, unable to require http.request method; reason: %w", err) } - // Export the http module's syncRequest function goja.Callable as a Go function + // Export the http module's syncRequest function sobek.Callable as a Go function var asyncRequestFunc HTTPAsyncRequestFunc if err := rt.ExportTo(httpModuleObject.Get("asyncRequest"), &asyncRequestFunc); err != nil { return nil, @@ -122,11 +122,11 @@ func (c *Client) Configure(opts options) error { // Request instruments the http module's request function with tracing headers, // and ensures the trace_id is emitted as part of the output's data points metadata. -func (c *Client) Request(method string, url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Request(method string, url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { var result *httpmodule.Response var err error - err = c.instrumentedCall(func(args ...goja.Value) error { + err = c.instrumentedCall(func(args ...sobek.Value) error { result, err = c.requestFunc(method, url, args...) return err }, args...) @@ -138,10 +138,10 @@ func (c *Client) Request(method string, url goja.Value, args ...goja.Value) (*ht // AsyncRequest instruments the http module's asyncRequest function with tracing headers, // and ensures the trace_id is emitted as part of the output's data points metadata. -func (c *Client) AsyncRequest(method string, url goja.Value, args ...goja.Value) (*goja.Promise, error) { - var result *goja.Promise +func (c *Client) AsyncRequest(method string, url sobek.Value, args ...sobek.Value) (*sobek.Promise, error) { + var result *sobek.Promise var err error - err = c.instrumentedCall(func(args ...goja.Value) error { + err = c.instrumentedCall(func(args ...sobek.Value) error { result, err = c.asyncRequestFunc(method, url, args...) return err }, args...) @@ -152,49 +152,49 @@ func (c *Client) AsyncRequest(method string, url goja.Value, args ...goja.Value) } // Del instruments the http module's delete method. -func (c *Client) Del(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Del(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { return c.Request(http.MethodDelete, url, args...) } // Get instruments the http module's get method. -func (c *Client) Get(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Get(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { // Here we prepend a null value that stands for the body parameter, // that the request function expects as a first argument implicitly - args = append([]goja.Value{goja.Null()}, args...) + args = append([]sobek.Value{sobek.Null()}, args...) return c.Request(http.MethodGet, url, args...) } // Head instruments the http module's head method. -func (c *Client) Head(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Head(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { // NB: here we prepend a null value that stands for the body parameter, // that the request function expects as a first argument implicitly - args = append([]goja.Value{goja.Null()}, args...) + args = append([]sobek.Value{sobek.Null()}, args...) return c.Request(http.MethodHead, url, args...) } // Options instruments the http module's options method. -func (c *Client) Options(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Options(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { return c.Request(http.MethodOptions, url, args...) } // Patch instruments the http module's patch method. -func (c *Client) Patch(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Patch(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { return c.Request(http.MethodPatch, url, args...) } // Post instruments the http module's post method. -func (c *Client) Post(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Post(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { return c.Request(http.MethodPost, url, args...) } // Put instruments the http module's put method. -func (c *Client) Put(url goja.Value, args ...goja.Value) (*httpmodule.Response, error) { +func (c *Client) Put(url sobek.Value, args ...sobek.Value) (*httpmodule.Response, error) { return c.Request(http.MethodPut, url, args...) } -func (c *Client) instrumentedCall(call func(args ...goja.Value) error, args ...goja.Value) error { +func (c *Client) instrumentedCall(call func(args ...sobek.Value) error, args ...sobek.Value) error { if len(args) == 0 { - args = []goja.Value{goja.Null()} + args = []sobek.Value{sobek.Null()} } traceContextHeader, encodedTraceID, err := c.generateTraceContext() @@ -242,10 +242,10 @@ func (c *Client) generateTraceContext() (http.Header, string, error) { // instrumentArguments: expects args to be in the format expected by the // request method (body, params) -func (c *Client) instrumentArguments(traceContext http.Header, args ...goja.Value) ([]goja.Value, error) { +func (c *Client) instrumentArguments(traceContext http.Header, args ...sobek.Value) ([]sobek.Value, error) { rt := c.vu.Runtime() - var paramsObj *goja.Object + var paramsObj *sobek.Object switch len(args) { case 2: diff --git a/js/modules/k6/experimental/tracing/client_test.go b/js/modules/k6/experimental/tracing/client_test.go index 7837e205362..574e1c3d116 100644 --- a/js/modules/k6/experimental/tracing/client_test.go +++ b/js/modules/k6/experimental/tracing/client_test.go @@ -5,7 +5,7 @@ import ( "net/http" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.k6.io/k6/js/modulestest" @@ -62,11 +62,11 @@ func TestClientInstrumentArguments(t *testing.T) { testCase := newTestCase(t) rt := testCase.testSetup.VU.Runtime() - gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, goja.Null()) + gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, sobek.Null()) assert.NoError(t, gotErr) assert.Len(t, gotArgs, 2) - assert.Equal(t, goja.Null(), gotArgs[0]) + assert.Equal(t, sobek.Null(), gotArgs[0]) gotParams := gotArgs[1].ToObject(rt) assert.NotNil(t, gotParams) @@ -83,11 +83,11 @@ func TestClientInstrumentArguments(t *testing.T) { testCase := newTestCase(t) rt := testCase.testSetup.VU.Runtime() - gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, goja.Null(), goja.Null()) + gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, sobek.Null(), sobek.Null()) assert.NoError(t, gotErr) assert.Len(t, gotArgs, 2) - assert.Equal(t, goja.Null(), gotArgs[0]) + assert.Equal(t, sobek.Null(), gotArgs[0]) gotParams := gotArgs[1].ToObject(rt) assert.NotNil(t, gotParams) @@ -104,11 +104,11 @@ func TestClientInstrumentArguments(t *testing.T) { testCase := newTestCase(t) rt := testCase.testSetup.VU.Runtime() - gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, goja.Null(), goja.Undefined()) + gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, sobek.Null(), sobek.Undefined()) assert.NoError(t, gotErr) assert.Len(t, gotArgs, 2) - assert.Equal(t, goja.Null(), gotArgs[0]) + assert.Equal(t, sobek.Null(), gotArgs[0]) gotParams := gotArgs[1].ToObject(rt) assert.NotNil(t, gotParams) @@ -130,11 +130,11 @@ func TestClientInstrumentArguments(t *testing.T) { wantParams := rt.NewObject() require.NoError(t, wantParams.Set("headers", wantHeaders)) - gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, goja.Null(), wantParams) + gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, sobek.Null(), wantParams) assert.NoError(t, gotErr) assert.Len(t, gotArgs, 2) - assert.Equal(t, goja.Null(), gotArgs[0]) + assert.Equal(t, sobek.Null(), gotArgs[0]) assert.Equal(t, wantParams, gotArgs[1]) gotHeaders := gotArgs[1].ToObject(rt).Get("headers").ToObject(rt) @@ -155,11 +155,11 @@ func TestClientInstrumentArguments(t *testing.T) { rt := testCase.testSetup.VU.Runtime() wantParams := rt.NewObject() - gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, goja.Null(), wantParams) + gotArgs, gotErr := testCase.client.instrumentArguments(testCase.traceContextHeader, sobek.Null(), wantParams) assert.NoError(t, gotErr) assert.Len(t, gotArgs, 2) - assert.Equal(t, goja.Null(), gotArgs[0]) + assert.Equal(t, sobek.Null(), gotArgs[0]) assert.Equal(t, wantParams, gotArgs[1]) gotHeaders := gotArgs[1].ToObject(rt).Get("headers").ToObject(rt) @@ -179,7 +179,7 @@ func TestClientInstrumentedCall(t *testing.T) { }) testCase.client.propagator = NewW3CPropagator(NewAlwaysOnSampler()) - callFn := func(_ ...goja.Value) error { + callFn := func(_ ...sobek.Value) error { gotMetadataTraceID, gotTraceIDKey := testCase.client.vu.State().Tags.GetCurrentValues().Metadata["trace_id"] assert.True(t, gotTraceIDKey) assert.NotEmpty(t, gotMetadataTraceID) diff --git a/js/modules/k6/experimental/tracing/module.go b/js/modules/k6/experimental/tracing/module.go index 6d53a973234..f0dbcb1c39c 100644 --- a/js/modules/k6/experimental/tracing/module.go +++ b/js/modules/k6/experimental/tracing/module.go @@ -7,7 +7,7 @@ import ( "math/rand" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" ) @@ -70,7 +70,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { // It expects a single configuration object as argument, which // will be used to instantiate an `Object` instance internally, // and will be used by the client to configure itself. -func (mi *ModuleInstance) newClient(cc goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) newClient(cc sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() if len(cc.Arguments) < 1 { @@ -93,7 +93,7 @@ func (mi *ModuleInstance) newClient(cc goja.ConstructorCall) *goja.Object { // // When used in the context of a k6 script, it will automatically replace // the imported http module's methods with instrumented ones. -func (mi *ModuleInstance) instrumentHTTP(options goja.Value) { +func (mi *ModuleInstance) instrumentHTTP(options sobek.Value) { rt := mi.vu.Runtime() if mi.vu.State() != nil { @@ -136,11 +136,11 @@ func (mi *ModuleInstance) instrumentHTTP(options goja.Value) { // Closure overriding a method of the provided imported module object. // - // The `onModule` argument should be a *goja.Object obtained by requiring + // The `onModule` argument should be a *sobek.Object obtained by requiring // or importing the 'k6/http' module and converting it to an object. // // The `value` argument is expected to be callable. - mustSetHTTPMethod := func(method string, onModule *goja.Object, value interface{}) { + mustSetHTTPMethod := func(method string, onModule *sobek.Object, value interface{}) { // Inject the new get function, adding tracing headers // to the request in the HTTP module object. err = onModule.Set(method, value) diff --git a/js/modules/k6/experimental/tracing/options.go b/js/modules/k6/experimental/tracing/options.go index cad3aa5024a..a65de41d189 100644 --- a/js/modules/k6/experimental/tracing/options.go +++ b/js/modules/k6/experimental/tracing/options.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" ) @@ -26,11 +26,11 @@ type options struct { // defaultSamplingRate is the default sampling rate applied to options. const defaultSamplingRate float64 = 1.0 -// newOptions returns a new options object from the given goja.Value. +// newOptions returns a new options object from the given sobek.Value. // // Note that if the sampling field value is absent, or nullish, we'll // set it to the `defaultSamplingRate` value. -func newOptions(rt *goja.Runtime, from goja.Value) (options, error) { +func newOptions(rt *sobek.Runtime, from sobek.Value) (options, error) { var opts options if err := rt.ExportTo(from, &opts); err != nil { diff --git a/js/modules/k6/grpc/client.go b/js/modules/k6/grpc/client.go index 8dd31804c31..2ff52484dc6 100644 --- a/js/modules/k6/grpc/client.go +++ b/js/modules/k6/grpc/client.go @@ -15,7 +15,7 @@ import ( "go.k6.io/k6/js/modules" "go.k6.io/k6/lib/netext/grpcext" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/jhump/protoreflect/desc" "github.com/jhump/protoreflect/desc/protoparse" "google.golang.org/grpc" @@ -205,7 +205,7 @@ func buildTLSConfigFromMap(parentConfig *tls.Config, tlsConfigMap map[string]int } // Connect is a block dial to the gRPC server at the given address (host:port) -func (c *Client) Connect(addr string, params goja.Value) (bool, error) { +func (c *Client) Connect(addr string, params sobek.Value) (bool, error) { state := c.vu.State() if state == nil { return false, common.NewInitContextError("connecting to a gRPC server in the init context is not supported") @@ -276,8 +276,8 @@ func (c *Client) Connect(addr string, params goja.Value) (bool, error) { // Invoke creates and calls a unary RPC by fully qualified method name func (c *Client) Invoke( method string, - req goja.Value, - params goja.Value, + req sobek.Value, + params sobek.Value, ) (*grpcext.InvokeResponse, error) { grpcReq, err := c.buildInvokeRequest(method, req, params) if err != nil { @@ -290,9 +290,9 @@ func (c *Client) Invoke( // AsyncInvoke creates and calls a unary RPC by fully qualified method name asynchronously func (c *Client) AsyncInvoke( method string, - req goja.Value, - params goja.Value, -) *goja.Promise { + req sobek.Value, + params sobek.Value, +) *sobek.Promise { grpcReq, err := c.buildInvokeRequest(method, req, params) promise, resolve, reject := c.vu.Runtime().NewPromise() @@ -321,8 +321,8 @@ func (c *Client) AsyncInvoke( // buildInvokeRequest creates a new InvokeRequest from the given method name, request object and parameters func (c *Client) buildInvokeRequest( method string, - req goja.Value, - params goja.Value, + req sobek.Value, + params sobek.Value, ) (grpcext.InvokeRequest, error) { grpcReq := grpcext.InvokeRequest{} diff --git a/js/modules/k6/grpc/grpc.go b/js/modules/k6/grpc/grpc.go index 8d9c4227509..e1b22c46227 100644 --- a/js/modules/k6/grpc/grpc.go +++ b/js/modules/k6/grpc/grpc.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/mstoykov/k6-taskqueue-lib/taskqueue" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" @@ -57,7 +57,7 @@ func (r *RootModule) NewModuleInstance(vu modules.VU) modules.Instance { } // NewClient is the JS constructor for the grpc Client. -func (mi *ModuleInstance) NewClient(_ goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) NewClient(_ sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() return rt.ToValue(&Client{vu: mi.vu}).ToObject(rt) } @@ -96,7 +96,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { } // stream returns a new stream object -func (mi *ModuleInstance) stream(c goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) stream(c sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() client, err := extractClient(c.Argument(0), rt) @@ -152,8 +152,8 @@ func (mi *ModuleInstance) stream(c goja.ConstructorCall) *goja.Object { return s.obj } -// extractClient extracts & validates a grpc.Client from a goja.Value. -func extractClient(v goja.Value, rt *goja.Runtime) (*Client, error) { +// extractClient extracts & validates a grpc.Client from a sobek.Value. +func extractClient(v sobek.Value, rt *sobek.Runtime) (*Client, error) { if common.IsNullish(v) { return nil, errors.New("empty gRPC client") } diff --git a/js/modules/k6/grpc/helpers_test.go b/js/modules/k6/grpc/helpers_test.go index b9c39023347..b65128096a7 100644 --- a/js/modules/k6/grpc/helpers_test.go +++ b/js/modules/k6/grpc/helpers_test.go @@ -5,13 +5,13 @@ import ( "strings" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.k6.io/k6/metrics" ) -func assertResponse(t *testing.T, cb codeBlock, err error, val goja.Value, ts testState) { +func assertResponse(t *testing.T, cb codeBlock, err error, val sobek.Value, ts testState) { if isWindows && cb.windowsErr != "" && err != nil { err = errors.New(strings.ReplaceAll(err.Error(), cb.windowsErr, cb.err)) } diff --git a/js/modules/k6/grpc/listeners.go b/js/modules/k6/grpc/listeners.go index 950a1ca19af..c1bd336e42a 100644 --- a/js/modules/k6/grpc/listeners.go +++ b/js/modules/k6/grpc/listeners.go @@ -3,7 +3,7 @@ package grpc import ( "fmt" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) const ( @@ -25,9 +25,9 @@ type eventListeners struct { type eventListener struct { eventType string - // this return goja.value *and* error in order to return error on exception instead of panic + // this return sobek.value *and* error in order to return error on exception instead of panic // https://pkg.go.dev/github.com/dop251/goja#hdr-Functions - list []func(goja.Value) (goja.Value, error) + list []func(sobek.Value) (sobek.Value, error) } // newListener creates a new listener of a certain type @@ -38,7 +38,7 @@ func newListener(eventType string) *eventListener { } // add adds a listener to the listener list -func (l *eventListener) add(fn func(goja.Value) (goja.Value, error)) { +func (l *eventListener) add(fn func(sobek.Value) (sobek.Value, error)) { l.list = append(l.list, fn) } @@ -59,7 +59,7 @@ func (l *eventListeners) getType(t string) *eventListener { } // add adds a listener to the listeners -func (l *eventListeners) add(t string, f func(goja.Value) (goja.Value, error)) error { +func (l *eventListeners) add(t string, f func(sobek.Value) (sobek.Value, error)) error { list := l.getType(t) if list == nil { @@ -72,11 +72,11 @@ func (l *eventListeners) add(t string, f func(goja.Value) (goja.Value, error)) e } // all returns all possible listeners for a certain event type or an empty array -func (l *eventListeners) all(t string) []func(goja.Value) (goja.Value, error) { +func (l *eventListeners) all(t string) []func(sobek.Value) (sobek.Value, error) { list := l.getType(t) if list == nil { - return []func(goja.Value) (goja.Value, error){} + return []func(sobek.Value) (sobek.Value, error){} } return list.list diff --git a/js/modules/k6/grpc/params.go b/js/modules/k6/grpc/params.go index d9fb9136b3c..f03d10bea13 100644 --- a/js/modules/k6/grpc/params.go +++ b/js/modules/k6/grpc/params.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/lib" @@ -25,7 +25,7 @@ type callParams struct { // newCallParams constructs the call parameters from the input value. // if no input is given, the default values are used. -func newCallParams(vu modules.VU, input goja.Value) (*callParams, error) { +func newCallParams(vu modules.VU, input sobek.Value) (*callParams, error) { result := &callParams{ Metadata: metadata.New(nil), TagsAndMeta: vu.State().Tags.GetCurrentValues(), @@ -67,7 +67,7 @@ func newCallParams(vu modules.VU, input goja.Value) (*callParams, error) { } // newMetadata constructs a metadata.MD from the input value. -func newMetadata(input goja.Value) (metadata.MD, error) { +func newMetadata(input sobek.Value) (metadata.MD, error) { md := metadata.New(nil) if common.IsNullish(input) { @@ -130,7 +130,7 @@ type connectParams struct { TLS map[string]interface{} } -func newConnectParams(vu modules.VU, input goja.Value) (*connectParams, error) { //nolint:gocognit +func newConnectParams(vu modules.VU, input sobek.Value) (*connectParams, error) { //nolint:gocognit result := &connectParams{ IsPlaintext: false, UseReflectionProtocol: false, diff --git a/js/modules/k6/grpc/params_test.go b/js/modules/k6/grpc/params_test.go index 7d3d8eb378e..62929a98054 100644 --- a/js/modules/k6/grpc/params_test.go +++ b/js/modules/k6/grpc/params_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -143,7 +143,7 @@ func TestCallParamsTimeOutParse(t *testing.T) { // that could be used to test the params // it also moves to the VU context and creates the params // goja value that could be used in the tests -func newParamsTestRuntime(t *testing.T, paramsJSON string) (*modulestest.Runtime, goja.Value) { +func newParamsTestRuntime(t *testing.T, paramsJSON string) (*modulestest.Runtime, sobek.Value) { t.Helper() testRuntime := modulestest.NewRuntime(t) diff --git a/js/modules/k6/grpc/stream.go b/js/modules/k6/grpc/stream.go index d4df1f480c6..69d3db7c269 100644 --- a/js/modules/k6/grpc/stream.go +++ b/js/modules/k6/grpc/stream.go @@ -14,7 +14,7 @@ import ( "go.k6.io/k6/lib/netext/grpcext" "go.k6.io/k6/metrics" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/mstoykov/k6-taskqueue-lib/taskqueue" "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" @@ -50,7 +50,7 @@ type stream struct { instanceMetrics *instanceMetrics builtinMetrics *metrics.BuiltinMetrics - obj *goja.Object // the object that is given to js to interact with the stream + obj *sobek.Object // the object that is given to js to interact with the stream writingState int8 done chan struct{} @@ -62,16 +62,16 @@ type stream struct { timeoutCancel context.CancelFunc } -// defineStream defines the goja.Object that is given to js to interact with the Stream -func defineStream(rt *goja.Runtime, s *stream) { +// defineStream defines the sobek.Object that is given to js to interact with the Stream +func defineStream(rt *sobek.Runtime, s *stream) { must(rt, s.obj.DefineDataProperty( - "on", rt.ToValue(s.on), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE)) + "on", rt.ToValue(s.on), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE)) must(rt, s.obj.DefineDataProperty( - "write", rt.ToValue(s.write), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE)) + "write", rt.ToValue(s.write), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE)) must(rt, s.obj.DefineDataProperty( - "end", rt.ToValue(s.end), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE)) + "end", rt.ToValue(s.end), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE)) } func (s *stream) beginStream(p *callParams) error { @@ -294,14 +294,14 @@ func (s *stream) processSendError(err error) { } // on registers a listener for a certain event type -func (s *stream) on(event string, listener func(goja.Value) (goja.Value, error)) { +func (s *stream) on(event string, listener func(sobek.Value) (sobek.Value, error)) { if err := s.eventListeners.add(event, listener); err != nil { s.vu.State().Logger.Warnf("can't register %s event handler: %s", event, err) } } // write writes a message to the stream -func (s *stream) write(input goja.Value) { +func (s *stream) write(input sobek.Value) { if s.writingState != opened { return } @@ -433,7 +433,7 @@ func (s *stream) callEventListeners(eventType string) error { } // must is a small helper that will panic if err is not nil. -func must(rt *goja.Runtime, err error) { +func must(rt *sobek.Runtime, err error) { if err != nil { common.Throw(rt, err) } diff --git a/js/modules/k6/grpc/stream_test.go b/js/modules/k6/grpc/stream_test.go index ad0d3d54aef..7c4eb804fc2 100644 --- a/js/modules/k6/grpc/stream_test.go +++ b/js/modules/k6/grpc/stream_test.go @@ -11,8 +11,8 @@ import ( "go.k6.io/k6/lib/testutils/grpcservice" "go.k6.io/k6/lib/testutils/httpmultibin/grpc_wrappers_testing" - "github.com/dop251/goja" "github.com/golang/protobuf/ptypes/wrappers" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" @@ -320,7 +320,7 @@ func TestStream_Wrappers(t *testing.T) { } } - replace := func(code string) (goja.Value, error) { + replace := func(code string) (sobek.Value, error) { return ts.VU.Runtime().RunString(ts.httpBin.Replacer.Replace(code)) } diff --git a/js/modules/k6/grpc/teststate_test.go b/js/modules/k6/grpc/teststate_test.go index 24ba46cfef6..e14de530926 100644 --- a/js/modules/k6/grpc/teststate_test.go +++ b/js/modules/k6/grpc/teststate_test.go @@ -8,7 +8,7 @@ import ( "sync" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "go.k6.io/k6/js/modulestest" @@ -83,12 +83,12 @@ type testState struct { } // Run replaces the httpbin address and runs the code. -func (ts *testState) Run(code string) (goja.Value, error) { +func (ts *testState) Run(code string) (sobek.Value, error) { return ts.VU.Runtime().RunString(ts.httpBin.Replacer.Replace(code)) } // RunOnEventLoop replaces the httpbin address and run the code on event loop -func (ts *testState) RunOnEventLoop(code string) (goja.Value, error) { +func (ts *testState) RunOnEventLoop(code string) (sobek.Value, error) { return ts.Runtime.RunOnEventLoop(ts.httpBin.Replacer.Replace(code)) } diff --git a/js/modules/k6/html/element.go b/js/modules/k6/html/element.go index 1fc8e27941b..f99323d9741 100644 --- a/js/modules/k6/html/element.go +++ b/js/modules/k6/html/element.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/PuerkitoBio/goquery" - "github.com/dop251/goja" + "github.com/grafana/sobek" gohtml "golang.org/x/net/html" ) @@ -113,15 +113,15 @@ func (e Element) ownerFormSel() (*goquery.Selection, bool) { return findForm, true } -func (e Element) ownerFormVal() goja.Value { +func (e Element) ownerFormVal() sobek.Value { formSel, exists := e.ownerFormSel() if !exists { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{e.sel.rt, formSel.Eq(0), e.sel.URL}) } -func (e Element) elemLabels() []goja.Value { +func (e Element) elemLabels() []sobek.Value { wrapperLbl := e.sel.sel.Closest("label") id := e.attrAsString("id") @@ -173,16 +173,16 @@ func (a Attribute) LocalName() string { return a.Name } -func (e Element) GetAttribute(name string) goja.Value { +func (e Element) GetAttribute(name string) sobek.Value { return e.sel.Attr(name) } -func (e Element) GetAttributeNode(name string) goja.Value { +func (e Element) GetAttributeNode(name string) sobek.Value { if attr := getHTMLAttr(e.node, name); attr != nil { return e.sel.rt.ToValue(Attribute{&e, attr.Key, attr.Namespace, attr.Val}) } - return goja.Undefined() + return sobek.Undefined() } func (e Element) HasAttribute(name string) bool { @@ -203,9 +203,9 @@ func (e Element) Attributes() map[string]Attribute { return attrs } -func (e Element) ToString() goja.Value { +func (e Element) ToString() sobek.Value { if e.sel.sel.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } if e.node.Type == gohtml.ElementNode { @@ -228,7 +228,7 @@ func (e Element) Id() string { return e.attrAsString("id") } -func (e Element) IsEqualNode(v goja.Value) bool { +func (e Element) IsEqualNode(v sobek.Value) bool { if other, ok := v.Export().(Element); ok { htmlA, errA := e.sel.sel.Html() htmlB, errB := other.sel.sel.Html() @@ -239,7 +239,7 @@ func (e Element) IsEqualNode(v goja.Value) bool { return false } -func (e Element) IsSameNode(v goja.Value) bool { +func (e Element) IsSameNode(v sobek.Value) bool { if other, ok := v.Export().(Element); ok { return e.node == other.node } @@ -259,19 +259,19 @@ func (e Element) Selection() Selection { return *e.sel } -func (e Element) GetElementsByClassName(name string) []goja.Value { +func (e Element) GetElementsByClassName(name string) []sobek.Value { return elemList(Selection{e.sel.rt, e.sel.sel.Find("." + name), e.sel.URL}) } -func (e Element) GetElementsByTagName(name string) []goja.Value { +func (e Element) GetElementsByTagName(name string) []sobek.Value { return elemList(Selection{e.sel.rt, e.sel.sel.Find(name), e.sel.URL}) } -func (e Element) QuerySelector(selector string) goja.Value { +func (e Element) QuerySelector(selector string) sobek.Value { return selToElement(Selection{e.sel.rt, e.sel.sel.Find(selector), e.sel.URL}) } -func (e Element) QuerySelectorAll(selector string) []goja.Value { +func (e Element) QuerySelectorAll(selector string) []sobek.Value { return elemList(Selection{e.sel.rt, e.sel.sel.Find(selector), e.sel.URL}) } @@ -279,75 +279,75 @@ func (e Element) NodeName() string { return goquery.NodeName(e.sel.sel) } -func (e Element) FirstChild() goja.Value { +func (e Element) FirstChild() sobek.Value { return nodeToElement(e, e.node.FirstChild) } -func (e Element) LastChild() goja.Value { +func (e Element) LastChild() sobek.Value { return nodeToElement(e, e.node.LastChild) } -func (e Element) FirstElementChild() goja.Value { +func (e Element) FirstElementChild() sobek.Value { if child := e.sel.sel.Children().First(); child.Length() > 0 { return selToElement(Selection{e.sel.rt, child.First(), e.sel.URL}) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) LastElementChild() goja.Value { +func (e Element) LastElementChild() sobek.Value { if child := e.sel.sel.Children(); child.Length() > 0 { return selToElement(Selection{e.sel.rt, child.Last(), e.sel.URL}) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) PreviousSibling() goja.Value { +func (e Element) PreviousSibling() sobek.Value { return nodeToElement(e, e.node.PrevSibling) } -func (e Element) NextSibling() goja.Value { +func (e Element) NextSibling() sobek.Value { return nodeToElement(e, e.node.NextSibling) } -func (e Element) PreviousElementSibling() goja.Value { +func (e Element) PreviousElementSibling() sobek.Value { if prev := e.sel.sel.Prev(); prev.Length() > 0 { return selToElement(Selection{e.sel.rt, prev, e.sel.URL}) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) NextElementSibling() goja.Value { +func (e Element) NextElementSibling() sobek.Value { if next := e.sel.sel.Next(); next.Length() > 0 { return selToElement(Selection{e.sel.rt, next, e.sel.URL}) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) ParentNode() goja.Value { +func (e Element) ParentNode() sobek.Value { if e.node.Parent != nil { return nodeToElement(e, e.node.Parent) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) ParentElement() goja.Value { +func (e Element) ParentElement() sobek.Value { if prt := e.sel.sel.Parent(); prt.Length() > 0 { return selToElement(Selection{e.sel.rt, prt, e.sel.URL}) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) ChildNodes() []goja.Value { +func (e Element) ChildNodes() []sobek.Value { return elemList(e.sel.Contents()) } -func (e Element) Children() []goja.Value { +func (e Element) Children() []sobek.Value { return elemList(e.sel.Children()) } @@ -363,24 +363,24 @@ func (e Element) ClassList() []string { return nil } -func (e Element) ClassName() goja.Value { +func (e Element) ClassName() sobek.Value { return e.sel.Attr("class") } -func (e Element) Lang() goja.Value { +func (e Element) Lang() sobek.Value { if attr := getHTMLAttr(e.node, "lang"); attr != nil && attr.Namespace == "" { return e.sel.rt.ToValue(attr.Val) } - return goja.Undefined() + return sobek.Undefined() } -func (e Element) OwnerDocument() goja.Value { +func (e Element) OwnerDocument() sobek.Value { if node := getOwnerDocNode(e.node); node != nil { return nodeToElement(e, node) } - return goja.Undefined() + return sobek.Undefined() } func (e Element) NamespaceURI() string { @@ -401,11 +401,11 @@ func getOwnerDocNode(node *gohtml.Node) *gohtml.Node { return nil } -func (e Element) InnerHTML() goja.Value { +func (e Element) InnerHTML() sobek.Value { return e.sel.Html() } -func (e Element) NodeType() goja.Value { +func (e Element) NodeType() sobek.Value { switch e.node.Type { case gohtml.TextNode: return e.sel.rt.ToValue(TextNode) @@ -423,11 +423,11 @@ func (e Element) NodeType() goja.Value { return e.sel.rt.ToValue(DoctypeNode) default: - return goja.Undefined() + return sobek.Undefined() } } -func (e Element) NodeValue() goja.Value { +func (e Element) NodeValue() sobek.Value { switch e.node.Type { case gohtml.TextNode: return e.sel.rt.ToValue(e.sel.Text()) @@ -436,11 +436,11 @@ func (e Element) NodeValue() goja.Value { return e.sel.rt.ToValue(e.sel.Text()) default: - return goja.Undefined() + return sobek.Undefined() } } -func (e Element) Contains(v goja.Value) bool { +func (e Element) Contains(v sobek.Value) bool { if other, ok := v.Export().(Element); ok { // When testing if a node contains itself, jquery's + goquery's version of Contains() // return true while the DOM API returns false. diff --git a/js/modules/k6/html/element_test.go b/js/modules/k6/html/element_test.go index f1f2fd03e31..2ed0ab8fe92 100644 --- a/js/modules/k6/html/element_test.go +++ b/js/modules/k6/html/element_test.go @@ -3,7 +3,7 @@ package html import ( "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" ) @@ -206,7 +206,7 @@ func TestElement(t *testing.T) { v, err := rt.RunString(`doc.find("div").get(0).childNodes()`) if assert.NoError(t, err) { - nodes, ok := v.Export().([]goja.Value) + nodes, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, 9, len(nodes)) @@ -220,7 +220,7 @@ func TestElement(t *testing.T) { v, err := rt.RunString(`doc.find("div").get(0).children()`) if assert.NoError(t, err) { - nodes, ok := v.Export().([]goja.Value) + nodes, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, 4, len(nodes)) @@ -358,7 +358,7 @@ func TestElement(t *testing.T) { v, err := rt.RunString(`doc.find("body").get(0).getElementsByClassName("class2")`) if assert.NoError(t, err) { - elems, ok := v.Export().([]goja.Value) + elems, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, "div_elem", elems[0].Export().(Element).Id()) @@ -371,7 +371,7 @@ func TestElement(t *testing.T) { v, err := rt.RunString(`doc.find("body").get(0).getElementsByTagName("span")`) if assert.NoError(t, err) { - elems, ok := v.Export().([]goja.Value) + elems, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, 2, len(elems)) @@ -392,7 +392,7 @@ func TestElement(t *testing.T) { v, err := rt.RunString(`doc.find("body").get(0).querySelectorAll("span")`) if assert.NoError(t, err) { - elems, ok := v.Export().([]goja.Value) + elems, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Len(t, elems, 2) diff --git a/js/modules/k6/html/elements.go b/js/modules/k6/html/elements.go index 22886eaffa8..3d56bb93642 100644 --- a/js/modules/k6/html/elements.go +++ b/js/modules/k6/html/elements.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) //go:generate go run gen/gen_elements.go @@ -266,7 +266,7 @@ func (h HrefElement) Text() string { return h.TextContent() } -func (f FormFieldElement) Form() goja.Value { +func (f FormFieldElement) Form() sobek.Value { return f.ownerFormVal() } @@ -340,7 +340,7 @@ func (f FormFieldElement) FormTarget() string { return target } -func (f FormFieldElement) Labels() []goja.Value { +func (f FormFieldElement) Labels() []sobek.Value { return f.elemLabels() } @@ -360,14 +360,14 @@ func (c CanvasElement) Height() int { return c.attrAsInt("height", 150) } -func (d DataListElement) Options() []goja.Value { +func (d DataListElement) Options() []sobek.Value { return elemList(d.sel.Find("option")) } -func (f FieldSetElement) Form() goja.Value { +func (f FieldSetElement) Form() sobek.Value { formSel, exists := f.ownerFormSel() if !exists { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{f.sel.rt, formSel, f.sel.URL}) } @@ -376,15 +376,15 @@ func (f FieldSetElement) Type() string { return "fieldset" } -func (f FieldSetElement) Elements() []goja.Value { +func (f FieldSetElement) Elements() []sobek.Value { return elemList(f.sel.Find("input,select,button,textarea")) } -func (f FieldSetElement) Validity() goja.Value { - return goja.Undefined() +func (f FieldSetElement) Validity() sobek.Value { + return sobek.Undefined() } -func (f FormElement) Elements() []goja.Value { +func (f FormElement) Elements() []sobek.Value { return elemList(f.sel.Find("input,select,button,textarea,fieldset")) } @@ -400,61 +400,61 @@ func (f FormElement) Method() string { return methodGet } -func (i InputElement) List() goja.Value { +func (i InputElement) List() sobek.Value { listID := i.attrAsString("list") if listID == "" { - return goja.Undefined() + return sobek.Undefined() } switch i.attrAsString("type") { case "hidden": - return goja.Undefined() + return sobek.Undefined() case "checkbox": - return goja.Undefined() + return sobek.Undefined() case "radio": - return goja.Undefined() + return sobek.Undefined() case "file": - return goja.Undefined() + return sobek.Undefined() case "button": - return goja.Undefined() + return sobek.Undefined() } datalist := i.sel.sel.Parents().Last().Find("datalist[id=\"" + listID + "\"]") if datalist.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{i.sel.rt, datalist.Eq(0), i.sel.URL}) } -func (k KeygenElement) Form() goja.Value { +func (k KeygenElement) Form() sobek.Value { return k.ownerFormVal() } -func (k KeygenElement) Labels() []goja.Value { +func (k KeygenElement) Labels() []sobek.Value { return k.elemLabels() } -func (l LabelElement) Control() goja.Value { +func (l LabelElement) Control() sobek.Value { forAttr, exists := l.sel.sel.Attr("for") if !exists { - return goja.Undefined() + return sobek.Undefined() } findControl := l.sel.sel.Parents().Last().Find("#" + forAttr) if findControl.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{l.sel.rt, findControl.Eq(0), l.sel.URL}) } -func (l LabelElement) Form() goja.Value { +func (l LabelElement) Form() sobek.Value { return l.ownerFormVal() } -func (l LegendElement) Form() goja.Value { +func (l LegendElement) Form() sobek.Value { return l.ownerFormVal() } @@ -462,26 +462,26 @@ func (l LinkElement) RelList() []string { return l.splitAttr("rel") } -func (m MapElement) Areas() []goja.Value { +func (m MapElement) Areas() []sobek.Value { return elemList(m.sel.Find("area")) } -func (m MapElement) Images() []goja.Value { +func (m MapElement) Images() []sobek.Value { name, exists := m.idOrNameAttr() if !exists { - return make([]goja.Value, 0) + return make([]sobek.Value, 0) } imgs := m.sel.sel.Parents().Last().Find("img[usemap=\"#" + name + "\"],object[usemap=\"#" + name + "\"]") return elemList(Selection{m.sel.rt, imgs, m.sel.URL}) } -func (m MeterElement) Labels() []goja.Value { +func (m MeterElement) Labels() []sobek.Value { return m.elemLabels() } -func (o ObjectElement) Form() goja.Value { +func (o ObjectElement) Form() sobek.Value { return o.ownerFormVal() } @@ -499,7 +499,7 @@ func (o OptionElement) Disabled() bool { return exists } -func (o OptionElement) Form() goja.Value { +func (o OptionElement) Form() sobek.Value { prtForm := o.sel.sel.ParentsFiltered("form") if prtForm.Length() != 0 { return selToElement(Selection{o.sel.rt, prtForm.First(), o.sel.URL}) @@ -508,12 +508,12 @@ func (o OptionElement) Form() goja.Value { prtSelect := o.sel.sel.ParentsFiltered("select") formID, exists := prtSelect.Attr("form") if !exists { - return goja.Undefined() + return sobek.Undefined() } ownerForm := prtSelect.Parents().Last().Find("form#" + formID) if ownerForm.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{o.sel.rt, ownerForm.First(), o.sel.URL}) @@ -544,11 +544,11 @@ func (o OptionElement) Value() string { return valueOrHTML(o.sel.sel) } -func (o OutputElement) Form() goja.Value { +func (o OutputElement) Form() sobek.Value { return o.ownerFormVal() } -func (o OutputElement) Labels() []goja.Value { +func (o OutputElement) Labels() []sobek.Value { return o.elemLabels() } @@ -596,7 +596,7 @@ func (p ProgressElement) Position() float64 { return p.calcProgress(-1.0) } -func (p ProgressElement) Labels() []goja.Value { +func (p ProgressElement) Labels() []sobek.Value { return p.elemLabels() } @@ -604,11 +604,11 @@ func (s ScriptElement) Text() string { return s.TextContent() } -func (s SelectElement) Form() goja.Value { +func (s SelectElement) Form() sobek.Value { return s.ownerFormVal() } -func (s SelectElement) Labels() []goja.Value { +func (s SelectElement) Labels() []sobek.Value { return s.elemLabels() } @@ -616,7 +616,7 @@ func (s SelectElement) Length() int { return s.sel.Find("option").Size() } -func (s SelectElement) Options() []goja.Value { +func (s SelectElement) Options() []sobek.Value { return elemList(Selection{s.sel.rt, s.sel.sel.Find("option"), s.sel.URL}) } @@ -628,7 +628,7 @@ func (s SelectElement) SelectedIndex() int { return s.sel.sel.Find("option").IndexOfSelection(option) } -func (s SelectElement) SelectedOptions() []goja.Value { +func (s SelectElement) SelectedOptions() []sobek.Value { return elemList(Selection{s.sel.rt, s.sel.sel.Find("option[selected]"), s.sel.URL}) } @@ -662,35 +662,35 @@ func (s StyleElement) Type() string { return typeVal } -func (t TableElement) firstChild(elemName string) goja.Value { +func (t TableElement) firstChild(elemName string) sobek.Value { child := t.sel.sel.ChildrenFiltered(elemName) if child.Size() == 0 { - return goja.Undefined() + return sobek.Undefined() } return selToElement(Selection{t.sel.rt, child, t.sel.URL}) } -func (t TableElement) Caption() goja.Value { +func (t TableElement) Caption() sobek.Value { return t.firstChild("caption") } -func (t TableElement) THead() goja.Value { +func (t TableElement) THead() sobek.Value { return t.firstChild("thead") } -func (t TableElement) TFoot() goja.Value { +func (t TableElement) TFoot() sobek.Value { return t.firstChild("tfoot") } -func (t TableElement) Rows() []goja.Value { +func (t TableElement) Rows() []sobek.Value { return elemList(Selection{t.sel.rt, t.sel.sel.Find("tr"), t.sel.URL}) } -func (t TableElement) TBodies() []goja.Value { +func (t TableElement) TBodies() []sobek.Value { return elemList(Selection{t.sel.rt, t.sel.sel.Find("tbody"), t.sel.URL}) } -func (t TableSectionElement) Rows() []goja.Value { +func (t TableSectionElement) Rows() []sobek.Value { return elemList(Selection{t.sel.rt, t.sel.sel.Find("tr"), t.sel.URL}) } @@ -702,7 +702,7 @@ func (t TableCellElement) CellIndex() int { return prtRow.Find("th,td").IndexOfSelection(t.sel.sel) } -func (t TableRowElement) Cells() []goja.Value { +func (t TableRowElement) Cells() []sobek.Value { return elemList(Selection{t.sel.rt, t.sel.sel.Find("th,td"), t.sel.URL}) } @@ -722,7 +722,7 @@ func (t TableRowElement) SectionRowIndex() int { return section.Find("tr").IndexOfSelection(t.sel.sel) } -func (t TextAreaElement) Form() goja.Value { +func (t TextAreaElement) Form() sobek.Value { return t.ownerFormVal() } @@ -730,7 +730,7 @@ func (t TextAreaElement) Length() int { return len(t.attrAsString("value")) } -func (t TextAreaElement) Labels() []goja.Value { +func (t TextAreaElement) Labels() []sobek.Value { return t.elemLabels() } @@ -742,7 +742,7 @@ func (t TableColElement) Span() int { return span } -func (m MediaElement) TextTracks() []goja.Value { +func (m MediaElement) TextTracks() []sobek.Value { return elemList(Selection{m.sel.rt, m.sel.sel.Find("track"), m.sel.URL}) } diff --git a/js/modules/k6/html/elements_gen.go b/js/modules/k6/html/elements_gen.go index cb8db340762..14a4361ca7b 100644 --- a/js/modules/k6/html/elements_gen.go +++ b/js/modules/k6/html/elements_gen.go @@ -1,11 +1,11 @@ // generated by js/modules/k6/html/gen/gen_elements.go; DO NOT EDIT package html -import "github.com/dop251/goja" +import "github.com/grafana/sobek" -func selToElement(sel Selection) goja.Value { +func selToElement(sel Selection) sobek.Value { if sel.sel.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } elem := Element{sel.sel.Nodes[0], &sel} @@ -200,10 +200,10 @@ func (m MediaElement) Src() string { return m.attrAsURLString("src", "") } -func (m MediaElement) CrossOrigin() goja.Value { +func (m MediaElement) CrossOrigin() sobek.Value { attrVal, exists := m.sel.sel.Attr("crossorigin") if !exists { - return goja.Undefined() + return sobek.Undefined() } switch attrVal { case "anonymous": @@ -211,7 +211,7 @@ func (m MediaElement) CrossOrigin() goja.Value { case "use-credentials": return m.sel.rt.ToValue(attrVal) default: - return goja.Undefined() + return sobek.Undefined() } } @@ -401,10 +401,10 @@ func (i ImageElement) Alt() string { return i.attrAsString("alt") } -func (i ImageElement) CrossOrigin() goja.Value { +func (i ImageElement) CrossOrigin() sobek.Value { attrVal, exists := i.sel.sel.Attr("crossorigin") if !exists { - return goja.Undefined() + return sobek.Undefined() } switch attrVal { case "anonymous": @@ -412,7 +412,7 @@ func (i ImageElement) CrossOrigin() goja.Value { case "use-credentials": return i.sel.rt.ToValue(attrVal) default: - return goja.Undefined() + return sobek.Undefined() } } @@ -686,10 +686,10 @@ func (l LiElement) Type() string { } } -func (l LinkElement) CrossOrigin() goja.Value { +func (l LinkElement) CrossOrigin() sobek.Value { attrVal, exists := l.sel.sel.Attr("crossorigin") if !exists { - return goja.Undefined() + return sobek.Undefined() } switch attrVal { case "anonymous": @@ -697,7 +697,7 @@ func (l LinkElement) CrossOrigin() goja.Value { case "use-credentials": return l.sel.rt.ToValue(attrVal) default: - return goja.Undefined() + return sobek.Undefined() } } diff --git a/js/modules/k6/html/elements_test.go b/js/modules/k6/html/elements_test.go index d6d903bbd5f..fb4a0321c56 100644 --- a/js/modules/k6/html/elements_test.go +++ b/js/modules/k6/html/elements_test.go @@ -3,7 +3,7 @@ package html import ( "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" ) @@ -291,13 +291,13 @@ func TestElements(t *testing.T) { rt := getTestRuntimeWithDoc(t, testHTMLElems) if v, err := rt.RunString(`doc.find("#form_btn").get(0).labels()`); assert.NoError(t, err) { - assert.Equal(t, 1, len(v.Export().([]goja.Value))) - assert.Equal(t, "form_btn_label", v.Export().([]goja.Value)[0].Export().(LabelElement).Id()) + assert.Equal(t, 1, len(v.Export().([]sobek.Value))) + assert.Equal(t, "form_btn_label", v.Export().([]sobek.Value)[0].Export().(LabelElement).Id()) } if v, err := rt.RunString(`doc.find("#form_btn_2").get(0).labels()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) - assert.Equal(t, "wrapper_label", v.Export().([]goja.Value)[0].Export().(LabelElement).Id()) - assert.Equal(t, "form_btn_2_label", v.Export().([]goja.Value)[1].Export().(LabelElement).Id()) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) + assert.Equal(t, "wrapper_label", v.Export().([]sobek.Value)[0].Export().(LabelElement).Id()) + assert.Equal(t, "form_btn_2_label", v.Export().([]sobek.Value)[1].Export().(LabelElement).Id()) } }) t.Run("name", func(t *testing.T) { @@ -342,9 +342,9 @@ func TestElements(t *testing.T) { rt := getTestRuntimeWithDoc(t, testHTMLElems) if v, err := rt.RunString(`doc.find("datalist").get(0).options()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) - assert.Equal(t, "dl_opt_1", v.Export().([]goja.Value)[0].Export().(OptionElement).Id()) - assert.Equal(t, "dl_opt_2", v.Export().([]goja.Value)[1].Export().(OptionElement).Id()) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) + assert.Equal(t, "dl_opt_1", v.Export().([]sobek.Value)[0].Export().(OptionElement).Id()) + assert.Equal(t, "dl_opt_2", v.Export().([]sobek.Value)[1].Export().(OptionElement).Id()) } }) t.Run("FieldSetElement", func(t *testing.T) { @@ -353,7 +353,7 @@ func TestElements(t *testing.T) { t.Run("elements", func(t *testing.T) { if v, err := rt.RunString(`doc.find("fieldset").get(0).elements()`); assert.NoError(t, err) { - assert.Equal(t, 5, len(v.Export().([]goja.Value))) + assert.Equal(t, 5, len(v.Export().([]sobek.Value))) } }) t.Run("type", func(t *testing.T) { @@ -373,7 +373,7 @@ func TestElements(t *testing.T) { t.Run("elements", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#fieldset_form").get(0).elements()`); assert.NoError(t, err) { - assert.Equal(t, 6, len(v.Export().([]goja.Value))) + assert.Equal(t, 6, len(v.Export().([]sobek.Value))) } }) t.Run("length", func(t *testing.T) { @@ -396,7 +396,7 @@ func TestElements(t *testing.T) { t.Run("form", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#test_dl_input").get(0).list().options()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) } }) }) @@ -441,12 +441,12 @@ func TestElements(t *testing.T) { t.Run("areas", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#find_this_map").get(0).areas()`); assert.NoError(t, err) { - assert.Equal(t, 3, len(v.Export().([]goja.Value))) + assert.Equal(t, 3, len(v.Export().([]sobek.Value))) } }) t.Run("images", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#find_this_map").get(0).images()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) } }) }) @@ -523,7 +523,7 @@ func TestElements(t *testing.T) { }) t.Run("labels", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#output1").get(0).labels()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) } }) }) @@ -582,14 +582,14 @@ func TestElements(t *testing.T) { }) t.Run("options", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#sel1").get(0).options()`); assert.NoError(t, err) { - assert.Equal(t, 3, len(v.Export().([]goja.Value))) - assert.Equal(t, "opt_1", v.Export().([]goja.Value)[0].Export().(OptionElement).Id()) + assert.Equal(t, 3, len(v.Export().([]sobek.Value))) + assert.Equal(t, "opt_1", v.Export().([]sobek.Value)[0].Export().(OptionElement).Id()) } }) t.Run("selectedOptions", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#sel1").get(0).selectedOptions()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) - assert.Equal(t, "opt_2", v.Export().([]goja.Value)[0].Export().(OptionElement).Id()) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) + assert.Equal(t, "opt_2", v.Export().([]sobek.Value)[0].Export().(OptionElement).Id()) } }) t.Run("selectedIndex", func(t *testing.T) { @@ -627,29 +627,29 @@ func TestElements(t *testing.T) { }) t.Run("thead", func(t *testing.T) { if v, err := rt.RunString(`doc.find("table").get(0).tHead().rows()`); assert.NoError(t, err) { - assert.Equal(t, 1, len(v.Export().([]goja.Value))) - assert.Equal(t, "thead_row", v.Export().([]goja.Value)[0].Export().(TableRowElement).Id()) + assert.Equal(t, 1, len(v.Export().([]sobek.Value))) + assert.Equal(t, "thead_row", v.Export().([]sobek.Value)[0].Export().(TableRowElement).Id()) } }) t.Run("tbody", func(t *testing.T) { if v, err := rt.RunString(`doc.find("table").get(0).tBodies()[0].rows()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) - assert.Equal(t, "tbody_row", v.Export().([]goja.Value)[1].Export().(TableRowElement).Id()) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) + assert.Equal(t, "tbody_row", v.Export().([]sobek.Value)[1].Export().(TableRowElement).Id()) } }) t.Run("tfoot", func(t *testing.T) { if v, err := rt.RunString(`doc.find("table").get(0).tFoot().rows()`); assert.NoError(t, err) { - assert.Equal(t, 3, len(v.Export().([]goja.Value))) - assert.Equal(t, "tfoot_row", v.Export().([]goja.Value)[2].Export().(TableRowElement).Id()) + assert.Equal(t, 3, len(v.Export().([]sobek.Value))) + assert.Equal(t, "tfoot_row", v.Export().([]sobek.Value)[2].Export().(TableRowElement).Id()) } }) t.Run("rows", func(t *testing.T) { if v, err := rt.RunString(`doc.find("table").get(0).rows()`); assert.NoError(t, err) { - assert.Equal(t, 7, len(v.Export().([]goja.Value))) - assert.Equal(t, "thead_row", v.Export().([]goja.Value)[0].Export().(TableRowElement).Id()) - assert.Equal(t, "tfoot_row", v.Export().([]goja.Value)[3].Export().(TableRowElement).Id()) - assert.Equal(t, "tbody_row", v.Export().([]goja.Value)[5].Export().(TableRowElement).Id()) - assert.Equal(t, "last_row", v.Export().([]goja.Value)[6].Export().(TableRowElement).Id()) + assert.Equal(t, 7, len(v.Export().([]sobek.Value))) + assert.Equal(t, "thead_row", v.Export().([]sobek.Value)[0].Export().(TableRowElement).Id()) + assert.Equal(t, "tfoot_row", v.Export().([]sobek.Value)[3].Export().(TableRowElement).Id()) + assert.Equal(t, "tbody_row", v.Export().([]sobek.Value)[5].Export().(TableRowElement).Id()) + assert.Equal(t, "last_row", v.Export().([]sobek.Value)[6].Export().(TableRowElement).Id()) } }) t.Run("TableCellElement", func(t *testing.T) { @@ -683,8 +683,8 @@ func TestElements(t *testing.T) { t.Run("TableRowElement", func(t *testing.T) { t.Run("cells", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#thead_row").get(0).cells()`); assert.NoError(t, err) { - assert.Equal(t, 3, len(v.Export().([]goja.Value))) - assert.Equal(t, "th_cell", v.Export().([]goja.Value)[1].Export().(TableHeaderCellElement).Id()) + assert.Equal(t, 3, len(v.Export().([]sobek.Value))) + assert.Equal(t, "th_cell", v.Export().([]sobek.Value)[1].Export().(TableHeaderCellElement).Id()) } }) t.Run("colSpan", func(t *testing.T) { @@ -719,9 +719,9 @@ func TestElements(t *testing.T) { t.Run("text tracks", func(t *testing.T) { if v, err := rt.RunString(`doc.find("#video1").get(0).textTracks()`); assert.NoError(t, err) { - assert.Equal(t, 2, len(v.Export().([]goja.Value))) - assert.Equal(t, "trk1", v.Export().([]goja.Value)[0].Export().(TrackElement).Id()) - assert.Equal(t, "trk2", v.Export().([]goja.Value)[1].Export().(TrackElement).Id()) + assert.Equal(t, 2, len(v.Export().([]sobek.Value))) + assert.Equal(t, "trk1", v.Export().([]sobek.Value)[0].Export().(TrackElement).Id()) + assert.Equal(t, "trk2", v.Export().([]sobek.Value)[1].Export().(TrackElement).Id()) } }) }) diff --git a/js/modules/k6/html/gen/gen_elements.go b/js/modules/k6/html/gen/gen_elements.go index ec4db2dd2a7..5f54d09b33c 100644 --- a/js/modules/k6/html/gen/gen_elements.go +++ b/js/modules/k6/html/gen/gen_elements.go @@ -84,7 +84,7 @@ var ( wrapOpts = []templateArg{"soft", "hard", "off"} kindOpts = []templateArg{"subtitle", "captions", "descriptions", "chapters", "metadata"} - // These are the values allowed for the crossorigin attribute, used by the nullableEnumTemplates is always goja.Undefined + // These are the values allowed for the crossorigin attribute, used by the nullableEnumTemplates is always sobek.Undefined crossOriginOpts = []templateArg{"anonymous", "use-credentials"} ) @@ -104,8 +104,8 @@ var ( // enumTemplate: uses any number or more TemplateArg, the gen'd func always returns one of the values in // the TemplateArgs. The first item in the list is used as the default when the attribute // was invalid or unset. -// nullableEnumTemplate: similar to the enumTemplate except the default is goja.Undefined and the -// return type is goja.Value +// nullableEnumTemplate: similar to the enumTemplate except the default is sobek.Undefined and the +// return type is sobek.Value // //nolint:gochecknoglobals var funcDefs = []struct { @@ -371,11 +371,11 @@ var elemFuncsTemplate = template.Must(template.New("").Funcs(template.FuncMap{ }).Parse(`// generated by js/modules/k6/html/gen/gen_elements.go; DO NOT EDIT package html -import "github.com/dop251/goja" +import "github.com/grafana/sobek" -func selToElement(sel Selection) goja.Value { +func selToElement(sel Selection) sobek.Value { if sel.sel.Length() == 0 { - return goja.Undefined() + return sobek.Undefined() } elem := Element{sel.sel.Nodes[0], &sel} @@ -411,7 +411,7 @@ func ({{ receiverName $funcDef.Elem }} {{$funcDef.Elem}}) {{$funcDef.Method}}() {{- else if eq $funcDef.TemplateType $templateTypes.GojaEnum }} attrVal, exists := {{ receiverName $funcDef.Elem }}.sel.sel.Attr("{{ $funcDef.Attr }}") if !exists { - return goja.Undefined() + return sobek.Undefined() } switch attrVal { {{- range $optVal := $funcDef.TemplateArgs }} @@ -419,7 +419,7 @@ func ({{ receiverName $funcDef.Elem }} {{$funcDef.Elem}}) {{$funcDef.Method}}() return {{ receiverName $funcDef.Elem }}.sel.rt.ToValue(attrVal) {{- end}} default: - return goja.Undefined() + return sobek.Undefined() } {{- else if eq $funcDef.TemplateType $templateTypes.Const }} return "{{ index $funcDef.TemplateArgs 0 }}" @@ -451,7 +451,7 @@ func returnType(tt templateType) string { case intTemplate: return "int" case nullableEnumTemplate: - return "goja.Value" + return "sobek.Value" default: return "string" } diff --git a/js/modules/k6/html/html.go b/js/modules/k6/html/html.go index fbbbc1673f6..4630c1db065 100644 --- a/js/modules/k6/html/html.go +++ b/js/modules/k6/html/html.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/PuerkitoBio/goquery" - "github.com/dop251/goja" + "github.com/grafana/sobek" gohtml "golang.org/x/net/html" "go.k6.io/k6/js/common" @@ -21,7 +21,7 @@ type RootModule struct{} type ModuleInstance struct { vu modules.VU rootModule *RootModule - exports *goja.Object + exports *sobek.Object } var ( @@ -60,7 +60,7 @@ func (mi *ModuleInstance) parseHTML(src string) (Selection, error) { } // ParseHTML parses the provided HTML source into a Selection object. -func ParseHTML(rt *goja.Runtime, src string) (Selection, error) { +func ParseHTML(rt *sobek.Runtime, src string) (Selection, error) { doc, err := goquery.NewDocumentFromReader(strings.NewReader(src)) if err != nil { return Selection{}, err @@ -69,7 +69,7 @@ func ParseHTML(rt *goja.Runtime, src string) (Selection, error) { } type Selection struct { - rt *goja.Runtime + rt *sobek.Runtime sel *goquery.Selection URL string `json:"url"` } @@ -79,7 +79,7 @@ func (s Selection) emptySelection() Selection { return s.Eq(s.Size()) } -func (s Selection) buildMatcher(v goja.Value, gojaFn goja.Callable) func(int, *goquery.Selection) bool { +func (s Selection) buildMatcher(v sobek.Value, gojaFn sobek.Callable) func(int, *goquery.Selection) bool { return func(idx int, sel *goquery.Selection) bool { fnRes, fnErr := gojaFn(v, s.rt.ToValue(idx), s.rt.ToValue(sel)) if fnErr != nil { @@ -105,7 +105,7 @@ func (s Selection) varargFnCall(arg interface{}, case Element: return Selection{s.rt, nodeFilter(v.node), s.URL} - case goja.Value: + case sobek.Value: return s.varargFnCall(v.Export(), strFilter, selFilter, nodeFilter) default: @@ -129,7 +129,7 @@ func (s Selection) adjacentUntil(until func(string) *goquery.Selection, untilSelection func(*goquery.Selection) *goquery.Selection, filteredUntil func(string, string) *goquery.Selection, filteredUntilSelection func(string, *goquery.Selection) *goquery.Selection, - def ...goja.Value, + def ...sobek.Value, ) Selection { switch len(def) { case 0: @@ -180,8 +180,8 @@ func (s Selection) Has(arg interface{}) Selection { return s.varargFnCall(arg, s.sel.Has, s.sel.HasSelection, s.sel.HasNodes) } -func (s Selection) Not(v goja.Value) Selection { - gojaFn, isFn := goja.AssertFunction(v) +func (s Selection) Not(v sobek.Value) Selection { + gojaFn, isFn := sobek.AssertFunction(v) if !isFn { return s.varargFnCall(v, s.sel.Not, s.sel.NotSelection, s.sel.NotNodes) } @@ -221,7 +221,7 @@ func (s Selection) Siblings(def ...string) Selection { // The arguments are: // 1st argument is the selector. Either a selector string, a Selection object, or nil // 2nd argument is the filter. Either a selector string or nil/undefined -func (s Selection) PrevUntil(def ...goja.Value) Selection { +func (s Selection) PrevUntil(def ...sobek.Value) Selection { return s.adjacentUntil( s.sel.PrevUntil, s.sel.PrevUntilSelection, @@ -235,7 +235,7 @@ func (s Selection) PrevUntil(def ...goja.Value) Selection { // The arguments are: // 1st argument is the selector. Either a selector string, a Selection object, or nil // 2nd argument is the filter. Either a selector string or nil/undefined -func (s Selection) NextUntil(def ...goja.Value) Selection { +func (s Selection) NextUntil(def ...sobek.Value) Selection { return s.adjacentUntil( s.sel.NextUntil, s.sel.NextUntilSelection, @@ -250,7 +250,7 @@ func (s Selection) NextUntil(def ...goja.Value) Selection { // The arguments are: // 1st argument is the selector. Either a selector string, a Selection object, or nil // 2nd argument is the filter. Either a selector string or nil/undefined -func (s Selection) ParentsUntil(def ...goja.Value) Selection { +func (s Selection) ParentsUntil(def ...sobek.Value) Selection { return s.adjacentUntil( s.sel.ParentsUntil, s.sel.ParentsUntilSelection, @@ -288,27 +288,27 @@ func (s Selection) Text() string { return s.sel.Text() } -func (s Selection) Attr(name string, def ...goja.Value) goja.Value { +func (s Selection) Attr(name string, def ...sobek.Value) sobek.Value { val, exists := s.sel.Attr(name) if !exists { if len(def) > 0 { return def[0] } - return goja.Undefined() + return sobek.Undefined() } return s.rt.ToValue(val) } //nolint:revive,stylecheck // var-naming wants this to be HTML but this will break the API -func (s Selection) Html() goja.Value { +func (s Selection) Html() sobek.Value { val, err := s.sel.Html() if err != nil { - return goja.Undefined() + return sobek.Undefined() } return s.rt.ToValue(val) } -func (s Selection) Val() goja.Value { +func (s Selection) Val() sobek.Value { switch goquery.NodeName(s.sel) { case InputTagName: val, exists := s.sel.Attr("value") @@ -344,7 +344,7 @@ func (s Selection) Val() goja.Value { return s.rt.ToValue(valueOrHTML(selected)) default: - return goja.Undefined() + return sobek.Undefined() } } @@ -356,8 +356,8 @@ func (s Selection) Children(def ...string) Selection { return Selection{s.rt, s.sel.ChildrenFiltered(def[0]), s.URL} } -func (s Selection) Each(v goja.Value) Selection { - gojaFn, isFn := goja.AssertFunction(v) +func (s Selection) Each(v sobek.Value) Selection { + gojaFn, isFn := sobek.AssertFunction(v) if !isFn { common.Throw(s.rt, errors.New("the argument to each() must be a function")) } @@ -371,7 +371,7 @@ func (s Selection) Each(v goja.Value) Selection { return Selection{s.rt, s.sel.Each(fn), s.URL} } -func (s Selection) Filter(v goja.Value) Selection { +func (s Selection) Filter(v sobek.Value) Selection { switch val := v.Export().(type) { case string: return Selection{s.rt, s.sel.Filter(val), s.URL} @@ -380,7 +380,7 @@ func (s Selection) Filter(v goja.Value) Selection { return Selection{s.rt, s.sel.FilterSelection(val.sel), s.URL} } - gojaFn, isFn := goja.AssertFunction(v) + gojaFn, isFn := sobek.AssertFunction(v) if !isFn { common.Throw(s.rt, errors.New("the argument to filter() must be a function, a selector or a selection")) } @@ -388,7 +388,7 @@ func (s Selection) Filter(v goja.Value) Selection { return Selection{s.rt, s.sel.FilterFunction(s.buildMatcher(v, gojaFn)), s.URL} } -func (s Selection) Is(v goja.Value) bool { +func (s Selection) Is(v sobek.Value) bool { switch val := v.Export().(type) { case string: return s.sel.Is(val) @@ -397,7 +397,7 @@ func (s Selection) Is(v goja.Value) bool { return s.sel.IsSelection(val.sel) default: - gojaFn, isFn := goja.AssertFunction(v) + gojaFn, isFn := sobek.AssertFunction(v) if !isFn { common.Throw(s.rt, errors.New("the argument to is() must be a function, a selector or a selection")) } @@ -407,13 +407,13 @@ func (s Selection) Is(v goja.Value) bool { } // Map implements ES5 Array.prototype.map -func (s Selection) Map(v goja.Value) []goja.Value { - gojaFn, isFn := goja.AssertFunction(v) +func (s Selection) Map(v sobek.Value) []sobek.Value { + gojaFn, isFn := sobek.AssertFunction(v) if !isFn { common.Throw(s.rt, errors.New("the argument to map() must be a function")) } - var values []goja.Value + var values []sobek.Value s.sel.Each(func(idx int, sel *goquery.Selection) { selection := &Selection{sel: sel, URL: s.URL, rt: s.rt} @@ -436,10 +436,10 @@ func (s Selection) Slice(start int, def ...int) Selection { return Selection{s.rt, s.sel.Slice(start, s.sel.Length()), s.URL} } -func (s Selection) Get(def ...int) goja.Value { +func (s Selection) Get(def ...int) sobek.Value { switch { case len(def) == 0: - var items []goja.Value + var items []sobek.Value for i := 0; i < len(s.sel.Nodes); i++ { items = append(items, selToElement(s.Eq(i))) } @@ -449,7 +449,7 @@ func (s Selection) Get(def ...int) goja.Value { return selToElement(s.Eq(def[0])) default: - return goja.Undefined() + return sobek.Undefined() } } @@ -461,7 +461,7 @@ func (s Selection) ToArray() []Selection { return items } -func (s Selection) Index(def ...goja.Value) int { +func (s Selection) Index(def ...sobek.Value) int { if len(def) == 0 { return s.sel.Index() } @@ -486,9 +486,9 @@ func (s Selection) Index(def ...goja.Value) int { // // When 0 arguments: Read all data from attributes beginning with "data-". // When 1 argument: Append argument to "data-" then find for a matching attribute -func (s Selection) Data(def ...string) goja.Value { +func (s Selection) Data(def ...string) sobek.Value { if s.sel.Length() == 0 || len(s.sel.Nodes[0].Attr) == 0 { - return goja.Undefined() + return sobek.Undefined() } if len(def) > 0 { @@ -496,7 +496,7 @@ func (s Selection) Data(def ...string) goja.Value { if exists { return s.rt.ToValue(convertDataAttrVal(val)) } - return goja.Undefined() + return sobek.Undefined() } data := make(map[string]interface{}) for _, attr := range s.sel.Nodes[0].Attr { diff --git a/js/modules/k6/html/html_test.go b/js/modules/k6/html/html_test.go index 19f3e912de9..01f117fa548 100644 --- a/js/modules/k6/html/html_test.go +++ b/js/modules/k6/html/html_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -66,8 +66,8 @@ const testXML = ` ` -func getTestModuleInstance(t testing.TB) (*goja.Runtime, *ModuleInstance) { - rt := goja.New() +func getTestModuleInstance(t testing.TB) (*sobek.Runtime, *ModuleInstance) { + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) ctx, cancel := context.WithCancel(context.Background()) @@ -92,7 +92,7 @@ func getTestModuleInstance(t testing.TB) (*goja.Runtime, *ModuleInstance) { return rt, mi } -func getTestRuntimeAndModuleInstanceWithDoc(t testing.TB, html string) (*goja.Runtime, *ModuleInstance) { +func getTestRuntimeAndModuleInstanceWithDoc(t testing.TB, html string) (*sobek.Runtime, *ModuleInstance) { t.Helper() rt, mi := getTestModuleInstance(t) @@ -106,7 +106,7 @@ func getTestRuntimeAndModuleInstanceWithDoc(t testing.TB, html string) (*goja.Ru return rt, mi } -func getTestRuntimeWithDoc(t testing.TB, html string) *goja.Runtime { +func getTestRuntimeWithDoc(t testing.TB, html string) *sobek.Runtime { t.Helper() rt, _ := getTestRuntimeAndModuleInstanceWithDoc(t, html) @@ -175,7 +175,7 @@ func TestParseHTML(t *testing.T) { t.Run("Unset", func(t *testing.T) { v, err := rt.RunString(`doc.find("h1").attr("class")`) if assert.NoError(t, err) { - assert.True(t, goja.IsUndefined(v), "v is not undefined: %v", v) + assert.True(t, sobek.IsUndefined(v), "v is not undefined: %v", v) } t.Run("Default", func(t *testing.T) { @@ -296,7 +296,7 @@ func TestParseHTML(t *testing.T) { t.Run("Invalid arg", func(t *testing.T) { _, err := rt.RunString(`doc.find("#select_multi option").each("");`) if assert.Error(t, err) { - assert.IsType(t, &goja.Exception{}, err) + assert.IsType(t, &sobek.Exception{}, err) assert.Contains(t, err.Error(), "must be a function") } }) @@ -411,7 +411,7 @@ func TestParseHTML(t *testing.T) { t.Run("Valid", func(t *testing.T) { v, err := rt.RunString(`doc.find("#select_multi option").map(function(idx, val) { return val.text() })`) if assert.NoError(t, err) { - mapped, ok := v.Export().([]goja.Value) + mapped, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, 3, len(mapped)) assert.Equal(t, "option 1", mapped[0].String()) @@ -447,14 +447,14 @@ func TestParseHTML(t *testing.T) { t.Run("Invalid arg", func(t *testing.T) { _, err := rt.RunString(`doc.find("#select_multi option").map("");`) if assert.Error(t, err) { - assert.IsType(t, &goja.Exception{}, err) + assert.IsType(t, &sobek.Exception{}, err) assert.Contains(t, err.Error(), "must be a function") } }) t.Run("Map with attr must return string", func(t *testing.T) { v, err := rt.RunString(`doc.find("#select_multi").map(function(idx, val) { return val.attr("name") })`) if assert.NoError(t, err) { - mapped, ok := v.Export().([]goja.Value) + mapped, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, 1, len(mapped)) assert.Equal(t, "select_multi", mapped[0].String()) @@ -813,7 +813,7 @@ func TestParseHTML(t *testing.T) { t.Run("No args", func(t *testing.T) { v, err := rt.RunString(`doc.find("body").children().get()`) if assert.NoError(t, err) { - elems, ok := v.Export().([]goja.Value) + elems, ok := v.Export().([]sobek.Value) assert.True(t, ok) assert.Equal(t, "h1", elems[0].Export().(Element).NodeName()) diff --git a/js/modules/k6/html/serialize.go b/js/modules/k6/html/serialize.go index 8b6e5f51ab9..75cd16eda87 100644 --- a/js/modules/k6/html/serialize.go +++ b/js/modules/k6/html/serialize.go @@ -4,12 +4,12 @@ import ( neturl "net/url" "github.com/PuerkitoBio/goquery" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) type FormValue struct { Name string - Value goja.Value + Value sobek.Value } func (s Selection) SerializeArray() []FormValue { @@ -47,9 +47,9 @@ func (s Selection) SerializeArray() []FormValue { return result } -func (s Selection) SerializeObject() map[string]goja.Value { +func (s Selection) SerializeObject() map[string]sobek.Value { formValues := s.SerializeArray() - result := make(map[string]goja.Value) + result := make(map[string]sobek.Value) for i := range formValues { formValue := formValues[i] result[formValue.Name] = formValue.Value diff --git a/js/modules/k6/html/serialize_test.go b/js/modules/k6/html/serialize_test.go index f2f4a4b2934..780c1ed4c41 100644 --- a/js/modules/k6/html/serialize_test.go +++ b/js/modules/k6/html/serialize_test.go @@ -3,7 +3,7 @@ package html import ( "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" ) @@ -137,7 +137,7 @@ func TestSerialize(t *testing.T) { v, err := rt.RunString(`doc.find("form").serializeObject()`) if assert.NoError(t, err) { - obj, ok := v.Export().(map[string]goja.Value) + obj, ok := v.Export().(map[string]sobek.Value) assert.True(t, ok) assert.Equal(t, 11, len(obj)) diff --git a/js/modules/k6/html/util.go b/js/modules/k6/html/util.go index 5abf1b8677e..86a039f4285 100644 --- a/js/modules/k6/html/util.go +++ b/js/modules/k6/html/util.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/PuerkitoBio/goquery" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/serenize/snaker" gohtml "golang.org/x/net/html" ) @@ -55,15 +55,15 @@ func getHTMLAttr(node *gohtml.Node, name string) *gohtml.Attribute { return nil } -func elemList(s Selection) (items []goja.Value) { - items = make([]goja.Value, s.Size()) +func elemList(s Selection) (items []sobek.Value) { + items = make([]sobek.Value, s.Size()) for i := 0; i < s.Size(); i++ { items[i] = selToElement(s.Eq(i)) } return items } -func nodeToElement(e Element, node *gohtml.Node) goja.Value { +func nodeToElement(e Element, node *gohtml.Node) sobek.Value { // Goquery does not expose a way to build a goquery.Selection with an arbitrary html.Node. // Workaround by adding a node to an empty Selection emptySel := e.sel.emptySelection() @@ -86,7 +86,7 @@ func toNumeric(val string) (float64, bool) { func convertDataAttrVal(val string) interface{} { if len(val) == 0 { - return goja.Undefined() + return sobek.Undefined() } if val[0] == '{' || val[0] == '[' { @@ -107,10 +107,10 @@ func convertDataAttrVal(val string) interface{} { return false case "null": - return goja.Undefined() + return sobek.Undefined() case "undefined": - return goja.Undefined() + return sobek.Undefined() default: if fltVal, isOk := toNumeric(val); isOk { diff --git a/js/modules/k6/http/cookiejar.go b/js/modules/k6/http/cookiejar.go index 332e19da270..4a68fbb2e87 100644 --- a/js/modules/k6/http/cookiejar.go +++ b/js/modules/k6/http/cookiejar.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" ) @@ -41,7 +41,7 @@ func (j CookieJar) CookiesForURL(url string) map[string][]string { } // Set sets a cookie for a particular url with the given name value and additional opts -func (j CookieJar) Set(url, name, value string, opts goja.Value) (bool, error) { +func (j CookieJar) Set(url, name, value string, opts sobek.Value) (bool, error) { rt := j.moduleInstance.vu.Runtime() u, err := neturl.Parse(url) @@ -51,7 +51,7 @@ func (j CookieJar) Set(url, name, value string, opts goja.Value) (bool, error) { c := http.Cookie{Name: name, Value: value} paramsV := opts - if paramsV != nil && !goja.IsUndefined(paramsV) && !goja.IsNull(paramsV) { + if paramsV != nil && !sobek.IsUndefined(paramsV) && !sobek.IsNull(paramsV) { params := paramsV.ToObject(rt) for _, k := range params.Keys() { switch strings.ToLower(k) { diff --git a/js/modules/k6/http/file_test.go b/js/modules/k6/http/file_test.go index 1d716ed1ffb..f9d27e7b345 100644 --- a/js/modules/k6/http/file_test.go +++ b/js/modules/k6/http/file_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/require" ) @@ -13,7 +13,7 @@ func TestHTTPFile(t *testing.T) { input := []byte{104, 101, 108, 108, 111} testCases := []struct { - input func(rt *goja.Runtime) interface{} + input func(rt *sobek.Runtime) interface{} args []string expected FileData expErr string @@ -22,24 +22,24 @@ func TestHTTPFile(t *testing.T) { // as File() calls time.Now(), so we'd need some time freezing/mocking // or refactoring, or to exclude the field from the assertion. { - func(*goja.Runtime) interface{} { return input }, + func(*sobek.Runtime) interface{} { return input }, []string{"test.bin"}, FileData{Data: input, Filename: "test.bin", ContentType: "application/octet-stream"}, "", }, { - func(*goja.Runtime) interface{} { return string(input) }, + func(*sobek.Runtime) interface{} { return string(input) }, []string{"test.txt", "text/plain"}, FileData{Data: input, Filename: "test.txt", ContentType: "text/plain"}, "", }, { - func(rt *goja.Runtime) interface{} { return rt.NewArrayBuffer(input) }, + func(rt *sobek.Runtime) interface{} { return rt.NewArrayBuffer(input) }, []string{"test-ab.bin"}, FileData{Data: input, Filename: "test-ab.bin", ContentType: "application/octet-stream"}, "", }, - {func(*goja.Runtime) interface{} { return struct{}{} }, []string{}, FileData{}, "GoError: invalid type struct {}, expected string, []byte or ArrayBuffer"}, + {func(*sobek.Runtime) interface{} { return struct{}{} }, []string{}, FileData{}, "GoError: invalid type struct {}, expected string, []byte or ArrayBuffer"}, } for i, tc := range testCases { @@ -48,13 +48,13 @@ func TestHTTPFile(t *testing.T) { t.Parallel() runtime, mi := getTestModuleInstance(t) rt := runtime.VU.RuntimeField - cal, _ := goja.AssertFunction(rt.ToValue(mi.file)) - args := make([]goja.Value, 1, len(tc.args)+1) + cal, _ := sobek.AssertFunction(rt.ToValue(mi.file)) + args := make([]sobek.Value, 1, len(tc.args)+1) args[0] = rt.ToValue(tc.input(rt)) for _, arg := range tc.args { args = append(args, rt.ToValue(arg)) } - _, err := cal(goja.Undefined(), args...) + _, err := cal(sobek.Undefined(), args...) if tc.expErr != "" { require.EqualError(t, err, tc.expErr) } else { diff --git a/js/modules/k6/http/http.go b/js/modules/k6/http/http.go index f817895e33d..5fcfc2ae1ed 100644 --- a/js/modules/k6/http/http.go +++ b/js/modules/k6/http/http.go @@ -4,7 +4,7 @@ import ( "net/http" "net/http/cookiejar" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/lib/netext" @@ -23,7 +23,7 @@ type ModuleInstance struct { vu modules.VU rootModule *RootModule defaultClient *Client - exports *goja.Object + exports *sobek.Object } var ( @@ -68,16 +68,16 @@ func (r *RootModule) NewModuleInstance(vu modules.VU) modules.Instance { // TODO: refactor so the Client actually has better APIs and these are // wrappers (facades) that convert the old k6 idiosyncratic APIs to the new // proper Client ones that accept Request objects and don't suck - mustExport("get", func(url goja.Value, args ...goja.Value) (*Response, error) { + mustExport("get", func(url sobek.Value, args ...sobek.Value) (*Response, error) { // http.get(url, params) doesn't have a body argument, so we add undefined // as the third argument to http.request(method, url, body, params) - args = append([]goja.Value{goja.Undefined()}, args...) + args = append([]sobek.Value{sobek.Undefined()}, args...) return mi.defaultClient.Request(http.MethodGet, url, args...) }) - mustExport("head", func(url goja.Value, args ...goja.Value) (*Response, error) { + mustExport("head", func(url sobek.Value, args ...sobek.Value) (*Response, error) { // http.head(url, params) doesn't have a body argument, so we add undefined // as the third argument to http.request(method, url, body, params) - args = append([]goja.Value{goja.Undefined()}, args...) + args = append([]sobek.Value{sobek.Undefined()}, args...) return mi.defaultClient.Request(http.MethodHead, url, args...) }) mustExport("post", mi.defaultClient.getMethodClosure(http.MethodPost)) @@ -115,7 +115,7 @@ func (mi *ModuleInstance) defineConstants() { rt := mi.vu.Runtime() mustAddProp := func(name, val string) { err := mi.exports.DefineDataProperty( - name, rt.ToValue(val), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE, + name, rt.ToValue(val), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE, ) if err != nil { common.Throw(rt, err) @@ -141,7 +141,7 @@ func (mi *ModuleInstance) defineConstants() { mustAddProp("OCSP_REASON_AA_COMPROMISE", netext.OCSP_REASON_AA_COMPROMISE) } -func (mi *ModuleInstance) newCookieJar(_ goja.ConstructorCall) *goja.Object { +func (mi *ModuleInstance) newCookieJar(_ sobek.ConstructorCall) *sobek.Object { rt := mi.vu.Runtime() jar, err := cookiejar.New(nil) if err != nil { @@ -151,7 +151,7 @@ func (mi *ModuleInstance) newCookieJar(_ goja.ConstructorCall) *goja.Object { } // getVUCookieJar returns the active cookie jar for the current VU. -func (mi *ModuleInstance) getVUCookieJar(_ goja.FunctionCall) goja.Value { +func (mi *ModuleInstance) getVUCookieJar(_ sobek.FunctionCall) sobek.Value { rt := mi.vu.Runtime() if state := mi.vu.State(); state != nil { return rt.ToValue(&CookieJar{mi, state.CookieJar}) diff --git a/js/modules/k6/http/request.go b/js/modules/k6/http/request.go index 856fdc87efc..efff9661339 100644 --- a/js/modules/k6/http/request.go +++ b/js/modules/k6/http/request.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "gopkg.in/guregu/null.v3" "go.k6.io/k6/js/common" @@ -28,15 +28,15 @@ var ErrHTTPForbiddenInInitContext = common.NewInitContextError( var ErrBatchForbiddenInInitContext = common.NewInitContextError( "Using batch in the init context is not supported") -func (c *Client) getMethodClosure(method string) func(url goja.Value, args ...goja.Value) (*Response, error) { - return func(url goja.Value, args ...goja.Value) (*Response, error) { +func (c *Client) getMethodClosure(method string) func(url sobek.Value, args ...sobek.Value) (*Response, error) { + return func(url sobek.Value, args ...sobek.Value) (*Response, error) { return c.Request(method, url, args...) } } // Request makes an http request of the provided `method` and returns a corresponding response by -// taking goja.Values as arguments -func (c *Client) Request(method string, url goja.Value, args ...goja.Value) (*Response, error) { +// taking sobek.Values as arguments +func (c *Client) Request(method string, url sobek.Value, args ...sobek.Value) (*Response, error) { state := c.moduleInstance.vu.State() if state == nil { return nil, ErrHTTPForbiddenInInitContext @@ -56,7 +56,7 @@ func (c *Client) Request(method string, url goja.Value, args ...goja.Value) (*Re return c.responseFromHTTPext(resp), nil } -func splitRequestArgs(args []goja.Value) (body interface{}, params goja.Value) { +func splitRequestArgs(args []sobek.Value) (body interface{}, params sobek.Value) { if len(args) > 0 { body = args[0].Export() } @@ -84,7 +84,7 @@ func (c *Client) handleParseRequestError(err error) (*Response, error) { // asyncRequest makes an http request of the provided `method` and returns a promise. All the networking is done off // the event loop and the returned promise will be resolved with the response or rejected with an error -func (c *Client) asyncRequest(method string, url goja.Value, args ...goja.Value) (*goja.Promise, error) { +func (c *Client) asyncRequest(method string, url sobek.Value, args ...sobek.Value) (*sobek.Promise, error) { state := c.moduleInstance.vu.State() if c.moduleInstance.vu.State() == nil { return nil, ErrHTTPForbiddenInInitContext @@ -124,7 +124,7 @@ func (c *Client) asyncRequest(method string, url goja.Value, args ...goja.Value) // processResponse stores the body as an ArrayBuffer if indicated by // respType. This is done here instead of in httpext.readResponseBody to avoid -// a reverse dependency on js/common or goja. +// a reverse dependency on js/common or sobek. func (c *Client) processResponse(resp *httpext.Response, respType httpext.ResponseType) { if respType == httpext.ResponseTypeBinary && resp.Body != nil { b, ok := resp.Body.([]byte) @@ -143,7 +143,7 @@ func (c *Client) responseFromHTTPext(resp *httpext.Response) *Response { // //nolint:gocyclo, cyclop, funlen, gocognit func (c *Client) parseRequest( - method string, reqURL, body interface{}, params goja.Value, + method string, reqURL, body interface{}, params sobek.Value, ) (*httpext.ParsedHTTPRequest, error) { rt := c.moduleInstance.vu.Runtime() state := c.moduleInstance.vu.State() @@ -151,7 +151,7 @@ func (c *Client) parseRequest( return nil, ErrHTTPForbiddenInInitContext } - if urlJSValue, ok := reqURL.(goja.Value); ok { + if urlJSValue, ok := reqURL.(sobek.Value); ok { reqURL = urlJSValue.Export() } u, err := httpext.ToURL(reqURL) @@ -253,7 +253,7 @@ func (c *Client) parseRequest( if body != nil { switch data := body.(type) { - case map[string]goja.Value: + case map[string]sobek.Value: // TODO: fix forms submission and serialization in k6/html before fixing this.. newData := map[string]interface{}{} for k, v := range data { @@ -262,7 +262,7 @@ func (c *Client) parseRequest( if err := handleObjectBody(newData); err != nil { return nil, err } - case goja.ArrayBuffer: + case sobek.ArrayBuffer: result.Body = bytes.NewBuffer(data.Bytes()) case map[string]interface{}: if err := handleObjectBody(data); err != nil { @@ -283,15 +283,15 @@ func (c *Client) parseRequest( result.ActiveJar = state.CookieJar } - // TODO: ditch goja.Value, reflections and Object and use a simple go map and type assertions? + // TODO: ditch sobek.Value, reflections and Object and use a simple go map and type assertions? //nolint: nestif - if params != nil && !goja.IsUndefined(params) && !goja.IsNull(params) { + if params != nil && !sobek.IsUndefined(params) && !sobek.IsNull(params) { params := params.ToObject(rt) for _, k := range params.Keys() { switch k { case "cookies": cookiesV := params.Get(k) - if goja.IsUndefined(cookiesV) || goja.IsNull(cookiesV) { + if sobek.IsUndefined(cookiesV) || sobek.IsNull(cookiesV) { continue } cookies := cookiesV.ToObject(rt) @@ -300,7 +300,7 @@ func (c *Client) parseRequest( } for _, key := range cookies.Keys() { cookieV := cookies.Get(key) - if goja.IsUndefined(cookieV) || goja.IsNull(cookieV) { + if sobek.IsUndefined(cookieV) || sobek.IsNull(cookieV) { continue } switch cookieV.ExportType() { @@ -321,7 +321,7 @@ func (c *Client) parseRequest( } case "headers": headersV := params.Get(k) - if goja.IsUndefined(headersV) || goja.IsNull(headersV) { + if sobek.IsUndefined(headersV) || sobek.IsNull(headersV) { continue } headers := headersV.ToObject(rt) @@ -337,7 +337,7 @@ func (c *Client) parseRequest( } case "jar": jarV := params.Get(k) - if goja.IsUndefined(jarV) || goja.IsNull(jarV) { + if sobek.IsUndefined(jarV) || sobek.IsNull(jarV) { continue } if v, ok := jarV.Export().(*CookieJar); ok { @@ -463,7 +463,7 @@ func (c *Client) prepareBatchObject(requests map[string]interface{}) ( // Batch makes multiple simultaneous HTTP requests. The provideds reqsV should be an array of request // objects. Batch returns an array of responses and/or error -func (c *Client) Batch(reqsV ...goja.Value) (interface{}, error) { +func (c *Client) Batch(reqsV ...sobek.Value) (interface{}, error) { state := c.moduleInstance.vu.State() if state == nil { return nil, ErrBatchForbiddenInInitContext @@ -521,7 +521,7 @@ func (c *Client) parseBatchRequest(key interface{}, val interface{}) (*httpext.P method = http.MethodGet ok bool body, reqURL interface{} - params goja.Value + params sobek.Value rt = c.moduleInstance.vu.Runtime() ) diff --git a/js/modules/k6/http/response.go b/js/modules/k6/http/response.go index 2a0961eb9fa..38d291c872e 100644 --- a/js/modules/k6/http/response.go +++ b/js/modules/k6/http/response.go @@ -8,7 +8,7 @@ import ( "net/url" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/tidwall/gjson" "go.k6.io/k6/js/common" @@ -62,7 +62,7 @@ func (res *Response) HTML(selector ...string) html.Selection { } // JSON parses the body of a response as JSON and returns it to the goja VM. -func (res *Response) JSON(selector ...string) goja.Value { +func (res *Response) JSON(selector ...string) sobek.Value { rt := res.client.moduleInstance.vu.Runtime() if res.Body == nil { @@ -83,7 +83,7 @@ func (res *Response) JSON(selector ...string) goja.Value { if hasSelector { if !res.validatedJSON { if !gjson.ValidBytes(body) { - return goja.Undefined() + return sobek.Undefined() } res.validatedJSON = true } @@ -91,7 +91,7 @@ func (res *Response) JSON(selector ...string) goja.Value { result := gjson.GetBytes(body, selector[0]) if !result.Exists() { - return goja.Undefined() + return sobek.Undefined() } return rt.ToValue(result.Value()) } @@ -136,13 +136,13 @@ func checkErrorInJSON(input []byte, offset int, err error) error { // TODO: document the actual arguments that can be provided // //nolint:funlen -func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { +func (res *Response) SubmitForm(args ...sobek.Value) (*Response, error) { rt := res.client.moduleInstance.vu.Runtime() formSelector := "form" submitSelector := "[type=\"submit\"]" - var fields map[string]goja.Value - requestParams := goja.Null() + var fields map[string]sobek.Value + requestParams := sobek.Null() if len(args) > 0 { params := args[0].ToObject(rt) for _, k := range params.Keys() { @@ -168,7 +168,7 @@ func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { methodAttr := form.Attr("method") var requestMethod string - if methodAttr == goja.Undefined() { + if methodAttr == sobek.Undefined() { // Use GET by default requestMethod = http.MethodGet } else { @@ -182,7 +182,7 @@ func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { actionAttr := form.Attr("action") var requestURL *url.URL - if actionAttr == goja.Undefined() { + if actionAttr == sobek.Undefined() { // Use the url of the response if no action is set requestURL = responseURL } else { @@ -200,7 +200,7 @@ func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { submit := form.Find(submitSelector) submitName := submit.Attr("name") submitValue := submit.Val() - if submitName != goja.Undefined() && submitValue != goja.Undefined() { + if submitName != sobek.Undefined() && submitValue != sobek.Undefined() { values[submitName.String()] = submitValue } @@ -215,7 +215,7 @@ func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { q.Add(k, v.String()) } requestURL.RawQuery = q.Encode() - return res.client.Request(requestMethod, rt.ToValue(requestURL.String()), goja.Null(), requestParams) + return res.client.Request(requestMethod, rt.ToValue(requestURL.String()), sobek.Null(), requestParams) } return res.client.Request( requestMethod, rt.ToValue(requestURL.String()), @@ -225,11 +225,11 @@ func (res *Response) SubmitForm(args ...goja.Value) (*Response, error) { // ClickLink parses the body as an html, looks for a link and than makes a request as if the link was // clicked -func (res *Response) ClickLink(args ...goja.Value) (*Response, error) { +func (res *Response) ClickLink(args ...sobek.Value) (*Response, error) { rt := res.client.moduleInstance.vu.Runtime() selector := "a[href]" - requestParams := goja.Null() + requestParams := sobek.Null() if len(args) > 0 { params := args[0].ToObject(rt) for _, k := range params.Keys() { @@ -252,7 +252,7 @@ func (res *Response) ClickLink(args ...goja.Value) (*Response, error) { common.Throw(rt, fmt.Errorf("no element found for selector '%s' in response '%s'", selector, res.URL)) } hrefAttr := link.Attr("href") - if hrefAttr == goja.Undefined() { + if hrefAttr == sobek.Undefined() { errmsg := fmt.Errorf("no valid href attribute value found on element '%s' in response '%s'", selector, res.URL) common.Throw(rt, errmsg) } @@ -262,5 +262,5 @@ func (res *Response) ClickLink(args ...goja.Value) (*Response, error) { } requestURL := responseURL.ResolveReference(hrefURL) - return res.client.Request(http.MethodGet, rt.ToValue(requestURL.String()), goja.Undefined(), requestParams) + return res.client.Request(http.MethodGet, rt.ToValue(requestURL.String()), sobek.Undefined(), requestParams) } diff --git a/js/modules/k6/http/response_callback.go b/js/modules/k6/http/response_callback.go index 94b49121c9d..2f68f502343 100644 --- a/js/modules/k6/http/response_callback.go +++ b/js/modules/k6/http/response_callback.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" ) @@ -39,7 +39,7 @@ func (e expectedStatuses) match(status int) bool { // expectedStatuses returns expectedStatuses object based on the provided arguments. // The arguments must be either integers or object of `{min: , max: }` // kind. The "integer"ness is checked by the Number.isInteger. -func (mi *ModuleInstance) expectedStatuses(args ...goja.Value) *expectedStatuses { +func (mi *ModuleInstance) expectedStatuses(args ...sobek.Value) *expectedStatuses { rt := mi.vu.Runtime() if len(args) == 0 { @@ -47,9 +47,9 @@ func (mi *ModuleInstance) expectedStatuses(args ...goja.Value) *expectedStatuses } var result expectedStatuses - jsIsInt, _ := goja.AssertFunction(rt.GlobalObject().Get("Number").ToObject(rt).Get("isInteger")) - isInt := func(a goja.Value) bool { - v, err := jsIsInt(goja.Undefined(), a) + jsIsInt, _ := sobek.AssertFunction(rt.GlobalObject().Get("Number").ToObject(rt).Get("isInteger")) + isInt := func(a sobek.Value) bool { + v, err := jsIsInt(sobek.Undefined(), a) return err == nil && v.ToBoolean() } @@ -81,8 +81,8 @@ func (mi *ModuleInstance) expectedStatuses(args ...goja.Value) *expectedStatuses // SetResponseCallback sets the responseCallback to the value provided. Supported values are // expectedStatuses object or a `null` which means that metrics shouldn't be tagged as failed and // `http_req_failed` should not be emitted - the behaviour previous to this -func (c *Client) SetResponseCallback(val goja.Value) { - if val != nil && !goja.IsNull(val) { +func (c *Client) SetResponseCallback(val sobek.Value) { + if val != nil && !sobek.IsNull(val) { // This is done this way as ExportTo exports functions to empty structs without an error if es, ok := val.Export().(*expectedStatuses); ok { c.responseCallback = es.match diff --git a/js/modules/k6/http/response_callback_test.go b/js/modules/k6/http/response_callback_test.go index b29ef48dfa9..d201d456b40 100644 --- a/js/modules/k6/http/response_callback_test.go +++ b/js/modules/k6/http/response_callback_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.k6.io/k6/lib" @@ -71,7 +71,7 @@ func TestExpectedStatuses(t *testing.T) { } require.Error(t, err) - var exc *goja.Exception + var exc *sobek.Exception errors.As(err, &exc) require.ErrorContains(t, exc, testCase.err) }) diff --git a/js/modules/k6/k6.go b/js/modules/k6/k6.go index a166d6b8631..b6ee91402d9 100644 --- a/js/modules/k6/k6.go +++ b/js/modules/k6/k6.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" @@ -68,8 +68,8 @@ func (mi *K6) Exports() modules.Exports { } // Fail is a fancy way of saying `throw "something"`. -func (*K6) Fail(msg string) (goja.Value, error) { - return goja.Undefined(), errors.New(msg) +func (*K6) Fail(msg string) (sobek.Value, error) { + return sobek.Undefined(), errors.New(msg) } // Sleep waits the provided seconds before continuing the execution. @@ -90,7 +90,7 @@ func (mi *K6) RandomSeed(seed int64) { } // Group wraps a function call and executes it within the provided group name. -func (mi *K6) Group(name string, val goja.Value) (goja.Value, error) { +func (mi *K6) Group(name string, val sobek.Value) (sobek.Value, error) { state := mi.vu.State() if state == nil { return nil, ErrGroupInInitContext @@ -99,18 +99,18 @@ func (mi *K6) Group(name string, val goja.Value) (goja.Value, error) { if common.IsNullish(val) { return nil, errors.New("group() requires a callback as a second argument") } - fn, ok := goja.AssertFunction(val) + fn, ok := sobek.AssertFunction(val) if !ok { return nil, errors.New("group() requires a callback as a second argument") } if common.IsAsyncFunction(mi.vu.Runtime(), val) { - return goja.Undefined(), fmt.Errorf(asyncFunctionNotSupportedMsg, "group") + return sobek.Undefined(), fmt.Errorf(asyncFunctionNotSupportedMsg, "group") } oldGroupName, _ := state.Tags.GetCurrentValues().Tags.Get(metrics.TagGroup.String()) // TODO: what are we doing if group is not tagged newGroupName, err := lib.NewGroupPath(oldGroupName, name) if err != nil { - return goja.Undefined(), err + return sobek.Undefined(), err } shouldUpdateTag := state.Options.SystemTags.Has(metrics.TagGroup) @@ -128,7 +128,7 @@ func (mi *K6) Group(name string, val goja.Value) (goja.Value, error) { }() startTime := time.Now() - ret, err := fn(goja.Undefined()) + ret, err := fn(sobek.Undefined()) t := time.Now() ctx := mi.vu.Context() @@ -147,7 +147,7 @@ func (mi *K6) Group(name string, val goja.Value) (goja.Value, error) { } // Check will emit check metrics for the provided checks. -func (mi *K6) Check(arg0, checks goja.Value, extras ...goja.Value) (bool, error) { +func (mi *K6) Check(arg0, checks sobek.Value, extras ...sobek.Value) (bool, error) { state := mi.vu.State() if state == nil { return false, ErrCheckInInitContext @@ -186,9 +186,9 @@ func (mi *K6) Check(arg0, checks goja.Value, extras ...goja.Value) (bool, error) } // Resolve callables into values. - fn, ok := goja.AssertFunction(val) + fn, ok := sobek.AssertFunction(val) if ok { - tmpVal, err := fn(goja.Undefined(), arg0) + tmpVal, err := fn(sobek.Undefined(), arg0) val = tmpVal if err != nil { val = rt.ToValue(false) diff --git a/js/modules/k6/metrics/metrics.go b/js/modules/k6/metrics/metrics.go index da807578354..5eb422ce17d 100644 --- a/js/modules/k6/metrics/metrics.go +++ b/js/modules/k6/metrics/metrics.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" @@ -25,13 +25,13 @@ type Metric struct { // ErrMetricsAddInInitContext is error returned when adding to metric is done in the init context var ErrMetricsAddInInitContext = common.NewInitContextError("Adding to metrics in the init context is not supported") -func (mi *ModuleInstance) newMetric(call goja.ConstructorCall, t metrics.MetricType) (*goja.Object, error) { +func (mi *ModuleInstance) newMetric(call sobek.ConstructorCall, t metrics.MetricType) (*sobek.Object, error) { initEnv := mi.vu.InitEnv() if initEnv == nil { return nil, errors.New("metrics must be declared in the init context") } rt := mi.vu.Runtime() - c, _ := goja.AssertFunction(rt.ToValue(func(name string, isTime ...bool) (*goja.Object, error) { + c, _ := sobek.AssertFunction(rt.ToValue(func(name string, isTime ...bool) (*sobek.Object, error) { valueType := metrics.Default if len(isTime) > 0 && isTime[0] { valueType = metrics.Time @@ -42,7 +42,7 @@ func (mi *ModuleInstance) newMetric(call goja.ConstructorCall, t metrics.MetricT } metric := &Metric{metric: m, vu: mi.vu} o := rt.NewObject() - err = o.DefineDataProperty("name", rt.ToValue(name), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE) + err = o.DefineDataProperty("name", rt.ToValue(name), sobek.FLAG_FALSE, sobek.FLAG_FALSE, sobek.FLAG_TRUE) if err != nil { return nil, err } @@ -74,7 +74,7 @@ func limitValue(v string) string { }, string(omitMsg)) } -func (m Metric) add(v goja.Value, addTags goja.Value) (bool, error) { +func (m Metric) add(v sobek.Value, addTags sobek.Value) (bool, error) { state := m.vu.State() if state == nil { return false, ErrMetricsAddInInitContext @@ -97,7 +97,7 @@ func (m Metric) add(v goja.Value, addTags goja.Value) (bool, error) { return raiseErr(fmt.Errorf("no value was provided for metric '%s', a number or a boolean value is expected", m.metric.Name)) } - if goja.IsNull(v) { + if sobek.IsNull(v) { return raiseNan() } @@ -165,7 +165,7 @@ func (mi *ModuleInstance) Exports() modules.Exports { } // XCounter is a counter constructor -func (mi *ModuleInstance) XCounter(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { +func (mi *ModuleInstance) XCounter(call sobek.ConstructorCall, rt *sobek.Runtime) *sobek.Object { v, err := mi.newMetric(call, metrics.Counter) if err != nil { common.Throw(rt, err) @@ -174,7 +174,7 @@ func (mi *ModuleInstance) XCounter(call goja.ConstructorCall, rt *goja.Runtime) } // XGauge is a gauge constructor -func (mi *ModuleInstance) XGauge(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { +func (mi *ModuleInstance) XGauge(call sobek.ConstructorCall, rt *sobek.Runtime) *sobek.Object { v, err := mi.newMetric(call, metrics.Gauge) if err != nil { common.Throw(rt, err) @@ -183,7 +183,7 @@ func (mi *ModuleInstance) XGauge(call goja.ConstructorCall, rt *goja.Runtime) *g } // XTrend is a trend constructor -func (mi *ModuleInstance) XTrend(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { +func (mi *ModuleInstance) XTrend(call sobek.ConstructorCall, rt *sobek.Runtime) *sobek.Object { v, err := mi.newMetric(call, metrics.Trend) if err != nil { common.Throw(rt, err) @@ -192,7 +192,7 @@ func (mi *ModuleInstance) XTrend(call goja.ConstructorCall, rt *goja.Runtime) *g } // XRate is a rate constructor -func (mi *ModuleInstance) XRate(call goja.ConstructorCall, rt *goja.Runtime) *goja.Object { +func (mi *ModuleInstance) XRate(call sobek.ConstructorCall, rt *sobek.Runtime) *sobek.Object { v, err := mi.newMetric(call, metrics.Rate) if err != nil { common.Throw(rt, err) diff --git a/js/modules/k6/metrics/metrics_test.go b/js/modules/k6/metrics/metrics_test.go index c8436250feb..4ec6b2cef20 100644 --- a/js/modules/k6/metrics/metrics_test.go +++ b/js/modules/k6/metrics/metrics_test.go @@ -6,7 +6,7 @@ import ( "io" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -27,7 +27,7 @@ type addTestValue struct { type addTest struct { val addTestValue - rt *goja.Runtime + rt *sobek.Runtime hook *testutils.SimpleLogrusHook samples chan metrics.SampleContainer isThrow bool @@ -100,7 +100,7 @@ func TestMetrics(t *testing.T) { mtyp: mtyp, valueType: valueType, } - test.rt = goja.New() + test.rt = sobek.New() test.rt.SetFieldNameMapper(common.FieldNameMapper{}) registry := metrics.NewRegistry() mii := &modulestest.VU{ @@ -169,7 +169,7 @@ func TestMetrics(t *testing.T) { func TestMetricGetName(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) mii := &modulestest.VU{ @@ -197,7 +197,7 @@ func TestMetricGetName(t *testing.T) { func TestMetricDuplicates(t *testing.T) { t.Parallel() - rt := goja.New() + rt := sobek.New() rt.SetFieldNameMapper(common.FieldNameMapper{}) mii := &modulestest.VU{ diff --git a/js/modules/k6/timers/timers.go b/js/modules/k6/timers/timers.go index fc4b0bae7f0..6a257a17b61 100644 --- a/js/modules/k6/timers/timers.go +++ b/js/modules/k6/timers/timers.go @@ -7,7 +7,7 @@ import ( "github.com/mstoykov/k6-taskqueue-lib/taskqueue" "github.com/sirupsen/logrus" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/modules" ) @@ -77,13 +77,13 @@ func (e *Timers) nextID() uint64 { return e.timerIDCounter } -func (e *Timers) call(callback goja.Callable, args []goja.Value) error { +func (e *Timers) call(callback sobek.Callable, args []sobek.Value) error { // TODO: investigate, not sure GlobalObject() is always the correct value for `this`? _, err := callback(e.vu.Runtime().GlobalObject(), args...) return err } -func (e *Timers) setTimeout(callback goja.Callable, delay float64, args ...goja.Value) uint64 { +func (e *Timers) setTimeout(callback sobek.Callable, delay float64, args ...sobek.Value) uint64 { id := e.nextID() e.timerInitialization(callback, delay, args, false, id) return id @@ -106,7 +106,7 @@ func (e *Timers) freeEventLoopIfPossible() { } } -func (e *Timers) setInterval(callback goja.Callable, delay float64, args ...goja.Value) uint64 { +func (e *Timers) setInterval(callback sobek.Callable, delay float64, args ...sobek.Value) uint64 { id := e.nextID() e.timerInitialization(callback, delay, args, true, id) return id @@ -119,7 +119,7 @@ func (e *Timers) clearInterval(id uint64) { // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialisation-steps // NOTE: previousId from the specification is always send and it is basically id func (e *Timers) timerInitialization( - callback goja.Callable, timeout float64, args []goja.Value, repeat bool, id uint64, + callback sobek.Callable, timeout float64, args []sobek.Value, repeat bool, id uint64, ) { // skip all the nesting stuff as we do not care about them if timeout < 0 { diff --git a/js/modules/k6/ws/ws.go b/js/modules/k6/ws/ws.go index 032b3c119fe..2190f175b07 100644 --- a/js/modules/k6/ws/ws.go +++ b/js/modules/k6/ws/ws.go @@ -16,8 +16,8 @@ import ( "sync" "time" - "github.com/dop251/goja" "github.com/gorilla/websocket" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" @@ -34,7 +34,7 @@ type ( // WS represents a module instance of the WebSocket module. WS struct { vu modules.VU - obj *goja.Object + obj *sobek.Object } ) @@ -69,11 +69,11 @@ var ErrWSInInitContext = common.NewInitContextError("using websockets in the ini // Socket is the representation of the websocket returned to the js. type Socket struct { - rt *goja.Runtime + rt *sobek.Runtime ctx context.Context //nolint:containedctx conn *websocket.Conn - eventHandlers map[string][]goja.Callable - scheduled chan goja.Callable + eventHandlers map[string][]sobek.Callable + scheduled chan sobek.Callable done chan struct{} shutdownOnce sync.Once @@ -100,7 +100,7 @@ type message struct { } type wsConnectArgs struct { - setupFn goja.Callable + setupFn sobek.Callable headers http.Header enableCompression bool cookieJar *cookiejar.Jar @@ -117,7 +117,7 @@ func (mi *WS) Exports() modules.Exports { // Connect establishes a WebSocket connection based on the parameters provided. // //nolint:funlen -func (mi *WS) Connect(url string, args ...goja.Value) (*HTTPResponse, error) { +func (mi *WS) Connect(url string, args ...sobek.Value) (*HTTPResponse, error) { ctx := mi.vu.Context() rt := mi.vu.Runtime() state := mi.vu.State() @@ -149,7 +149,7 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*HTTPResponse, error) { defer socket.Close() // Run the user-provided set up function - if _, err := parsedArgs.setupFn(goja.Undefined(), rt.ToValue(&socket)); err != nil { + if _, err := parsedArgs.setupFn(sobek.Undefined(), rt.ToValue(&socket)); err != nil { _ = socket.closeConnection(websocket.CloseGoingAway) return nil, err } @@ -226,7 +226,7 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*HTTPResponse, error) { _ = socket.closeConnection(code) case scheduledFn := <-socket.scheduled: - if _, err := scheduledFn(goja.Undefined()); err != nil { + if _, err := scheduledFn(sobek.Undefined()); err != nil { _ = socket.closeConnection(websocket.CloseGoingAway) return nil, err } @@ -244,7 +244,7 @@ func (mi *WS) Connect(url string, args ...goja.Value) (*HTTPResponse, error) { } func (mi *WS) dial( - ctx context.Context, state *lib.State, rt *goja.Runtime, url string, + ctx context.Context, state *lib.State, rt *sobek.Runtime, url string, args *wsConnectArgs, ) (*Socket, *http.Response, func(), error) { // Overriding the NextProtos to avoid talking http2 @@ -294,9 +294,9 @@ func (mi *WS) dial( ctx: ctx, rt: rt, conn: conn, - eventHandlers: make(map[string][]goja.Callable), + eventHandlers: make(map[string][]sobek.Callable), pingSendTimestamps: make(map[string]time.Time), - scheduled: make(chan goja.Callable), + scheduled: make(chan sobek.Callable), done: make(chan struct{}), samplesOutput: state.Samples, tagsAndMeta: args.tagsAndMeta, @@ -309,16 +309,16 @@ func (mi *WS) dial( } // On is used to configure what the websocket should do on each event. -func (s *Socket) On(event string, handler goja.Value) { - if handler, ok := goja.AssertFunction(handler); ok { +func (s *Socket) On(event string, handler sobek.Value) { + if handler, ok := sobek.AssertFunction(handler); ok { s.eventHandlers[event] = append(s.eventHandlers[event], handler) } } -func (s *Socket) handleEvent(event string, args ...goja.Value) { +func (s *Socket) handleEvent(event string, args ...sobek.Value) { if handlers, ok := s.eventHandlers[event]; ok { for _, handler := range handlers { - if _, err := handler(goja.Undefined(), args...); err != nil { + if _, err := handler(sobek.Undefined(), args...); err != nil { common.Throw(s.rt, err) } } @@ -343,20 +343,20 @@ func (s *Socket) Send(message string) { } // SendBinary writes the given ArrayBuffer message to the connection. -func (s *Socket) SendBinary(message goja.Value) { +func (s *Socket) SendBinary(message sobek.Value) { if message == nil { common.Throw(s.rt, errors.New("missing argument, expected ArrayBuffer")) } msg := message.Export() - if ab, ok := msg.(goja.ArrayBuffer); ok { + if ab, ok := msg.(sobek.ArrayBuffer); ok { if err := s.conn.WriteMessage(websocket.BinaryMessage, ab.Bytes()); err != nil { s.handleEvent("error", s.rt.ToValue(err)) } } else { var jsType string switch { - case goja.IsNull(message), goja.IsUndefined(message): + case sobek.IsNull(message), sobek.IsUndefined(message): jsType = message.String() default: jsType = message.ToObject(s.rt).Get("constructor").ToObject(s.rt).Get("name").String() @@ -414,7 +414,7 @@ func (s *Socket) trackPong(pingID string) { // SetTimeout executes the provided function inside the socket's event loop after at least the provided // timeout, which is in ms, has elapsed -func (s *Socket) SetTimeout(fn goja.Callable, timeoutMs float64) error { +func (s *Socket) SetTimeout(fn sobek.Callable, timeoutMs float64) error { // Starts a goroutine, blocks once on the timeout and pushes the callable // back to the main loop through the scheduled channel. // @@ -443,7 +443,7 @@ func (s *Socket) SetTimeout(fn goja.Callable, timeoutMs float64) error { // SetInterval executes the provided function inside the socket's event loop each interval time, which is // in ms -func (s *Socket) SetInterval(fn goja.Callable, intervalMs float64) error { +func (s *Socket) SetInterval(fn sobek.Callable, intervalMs float64) error { // Starts a goroutine, blocks forever on the ticker and pushes the callable // back to the main loop through the scheduled channel. // @@ -476,7 +476,7 @@ func (s *Socket) SetInterval(fn goja.Callable, intervalMs float64) error { } // Close closes the webscocket. If providede the first argument will be used as the code for the close message. -func (s *Socket) Close(args ...goja.Value) { +func (s *Socket) Close(args ...sobek.Value) { code := websocket.CloseGoingAway if len(args) > 0 { code = int(args[0].ToInteger()) @@ -622,21 +622,21 @@ func wrapHTTPResponse(httpResponse *http.Response) (*HTTPResponse, error) { } //nolint:gocognit -func parseConnectArgs(state *lib.State, rt *goja.Runtime, args ...goja.Value) (*wsConnectArgs, error) { +func parseConnectArgs(state *lib.State, rt *sobek.Runtime, args ...sobek.Value) (*wsConnectArgs, error) { // The params argument is optional - var callableV, paramsV goja.Value + var callableV, paramsV sobek.Value switch len(args) { case 2: paramsV = args[0] callableV = args[1] case 1: - paramsV = goja.Undefined() + paramsV = sobek.Undefined() callableV = args[0] default: return nil, errors.New("invalid number of arguments to ws.connect") } // Get the callable (required) - setupFn, isFunc := goja.AssertFunction(callableV) + setupFn, isFunc := sobek.AssertFunction(callableV) if !isFunc { return nil, errors.New("last argument to ws.connect must be a function") } @@ -651,7 +651,7 @@ func parseConnectArgs(state *lib.State, rt *goja.Runtime, args ...goja.Value) (* tagsAndMeta: &tagsAndMeta, } - if goja.IsUndefined(paramsV) || goja.IsNull(paramsV) { + if sobek.IsUndefined(paramsV) || sobek.IsNull(paramsV) { return parsedArgs, nil } @@ -661,7 +661,7 @@ func parseConnectArgs(state *lib.State, rt *goja.Runtime, args ...goja.Value) (* switch k { case "headers": headersV := params.Get(k) - if goja.IsUndefined(headersV) || goja.IsNull(headersV) { + if sobek.IsUndefined(headersV) || sobek.IsNull(headersV) { continue } headersObj := headersV.ToObject(rt) @@ -677,7 +677,7 @@ func parseConnectArgs(state *lib.State, rt *goja.Runtime, args ...goja.Value) (* } case "jar": jarV := params.Get(k) - if goja.IsUndefined(jarV) || goja.IsNull(jarV) { + if sobek.IsUndefined(jarV) || sobek.IsNull(jarV) { continue } if v, ok := jarV.Export().(*httpModule.CookieJar); ok { diff --git a/js/modules/modules.go b/js/modules/modules.go index 5296573f8cd..a01101257b0 100644 --- a/js/modules/modules.go +++ b/js/modules/modules.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/ext" "go.k6.io/k6/js/common" "go.k6.io/k6/lib" @@ -56,8 +56,8 @@ type VU interface { // State returns lib.State if any is present State() *lib.State - // Runtime returns the goja.Runtime for the current VU - Runtime() *goja.Runtime + // Runtime returns the sobek.Runtime for the current VU + Runtime() *sobek.Runtime // RegisterCallback lets a JS module declare that it wants to run a function // on the event loop *at a later point in time*. See the documentation for diff --git a/js/modules/require_impl.go b/js/modules/require_impl.go index 0f0833eaaac..80975f126e9 100644 --- a/js/modules/require_impl.go +++ b/js/modules/require_impl.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/loader" ) @@ -31,7 +31,7 @@ func NewLegacyRequireImpl(vu VU, ms *ModuleSystem, pwd url.URL) *LegacyRequireIm const issueLink = "https://github.com/grafana/k6/issues/3534" // Require is the actual call that implements require -func (r *LegacyRequireImpl) Require(specifier string) (*goja.Object, error) { +func (r *LegacyRequireImpl) Require(specifier string) (*sobek.Object, error) { // TODO remove this in the future when we address https://github.com/grafana/k6/issues/2674 // This is currently needed as each time require is called we need to record it's new pwd // to be used if a require *or* open is used within the file as they are relative to the @@ -124,17 +124,17 @@ func (r *LegacyRequireImpl) warnUserOnPathResolutionDifferences(specifier string } } -func getCurrentModuleScript(rt *goja.Runtime) string { +func getCurrentModuleScript(rt *sobek.Runtime) string { var parent string - var buf [2]goja.StackFrame + var buf [2]sobek.StackFrame frames := rt.CaptureCallStack(2, buf[:0]) parent = frames[1].SrcName() return parent } -func getPreviousRequiringFile(rt *goja.Runtime) (string, error) { - var buf [1000]goja.StackFrame +func getPreviousRequiringFile(rt *sobek.Runtime) (string, error) { + var buf [1000]sobek.StackFrame frames := rt.CaptureCallStack(1000, buf[:0]) for i, frame := range frames[1:] { // first one should be the current require diff --git a/js/modules/resolution.go b/js/modules/resolution.go index bc7efa34710..d13a0b5d66b 100644 --- a/js/modules/resolution.go +++ b/js/modules/resolution.go @@ -5,7 +5,7 @@ import ( "net/url" "strings" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/compiler" "go.k6.io/k6/loader" ) @@ -21,7 +21,7 @@ type module interface { type moduleInstance interface { execute() error - exports() *goja.Object + exports() *sobek.Object } type moduleCacheElement struct { mod module @@ -162,7 +162,7 @@ func NewModuleSystem(resolver *ModuleResolver, vu VU) *ModuleSystem { } // Require is called when a module/file needs to be loaded by a script -func (ms *ModuleSystem) Require(pwd *url.URL, arg string) (*goja.Object, error) { +func (ms *ModuleSystem) Require(pwd *url.URL, arg string) (*sobek.Object, error) { mod, err := ms.resolver.resolve(pwd, arg) if err != nil { return nil, err @@ -185,8 +185,8 @@ func (ms *ModuleSystem) Require(pwd *url.URL, arg string) (*goja.Object, error) // it will be used instead of reevaluating the source from the provided SourceData. // // TODO: this API will likely change as native ESM support will likely not let us have the exports -// as one big goja.Value that we can manipulate -func (ms *ModuleSystem) RunSourceData(source *loader.SourceData) (goja.Value, error) { +// as one big sobek.Value that we can manipulate +func (ms *ModuleSystem) RunSourceData(source *loader.SourceData) (sobek.Value, error) { specifier := source.URL.String() pwd := source.URL.JoinPath("../") if _, err := ms.resolver.resolveLoaded(pwd, specifier, source.Data); err != nil { @@ -197,7 +197,7 @@ func (ms *ModuleSystem) RunSourceData(source *loader.SourceData) (goja.Value, er // ExportGloballyModule sets all exports of the provided module name on the globalThis. // effectively making them globally available -func ExportGloballyModule(rt *goja.Runtime, modSys *ModuleSystem, moduleName string) { +func ExportGloballyModule(rt *sobek.Runtime, modSys *ModuleSystem, moduleName string) { t, _ := modSys.Require(nil, moduleName) for _, key := range t.Keys() { diff --git a/js/modules_vu.go b/js/modules_vu.go index ff0a42768dc..8db0da82d45 100644 --- a/js/modules_vu.go +++ b/js/modules_vu.go @@ -3,7 +3,7 @@ package js import ( "context" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/event" "go.k6.io/k6/js/common" "go.k6.io/k6/js/eventloop" @@ -18,7 +18,7 @@ type moduleVUImpl struct { ctx context.Context initEnv *common.InitEnvironment state *lib.State - runtime *goja.Runtime + runtime *sobek.Runtime eventLoop *eventloop.EventLoop events events } @@ -39,7 +39,7 @@ func (m *moduleVUImpl) State() *lib.State { return m.state } -func (m *moduleVUImpl) Runtime() *goja.Runtime { +func (m *moduleVUImpl) Runtime() *sobek.Runtime { return m.runtime } diff --git a/js/modulestest/compile.go b/js/modulestest/compile.go index 06aedeec61b..7a544ae1c26 100644 --- a/js/modulestest/compile.go +++ b/js/modulestest/compile.go @@ -5,20 +5,20 @@ import ( "path" "path/filepath" - "github.com/dop251/goja" + "github.com/grafana/sobek" ) -// CompileFile compiles a JS file as a [*goja.Program]. +// CompileFile compiles a JS file as a [*sobek.Program]. // // The base path is used to resolve the file path. The name is the file name. // -// This function facilitates evaluating javascript test files in a [goja.Runtime] using -// the [goja.Runtime.RunProgram] method. -func CompileFile(base, name string) (*goja.Program, error) { +// This function facilitates evaluating javascript test files in a [sobek.Runtime] using +// the [sobek.Runtime.RunProgram] method. +func CompileFile(base, name string) (*sobek.Program, error) { b, err := os.ReadFile(filepath.Clean(path.Join(base, name))) //nolint:forbidigo if err != nil { return nil, err } - return goja.Compile(name, string(b), false) + return sobek.Compile(name, string(b), false) } diff --git a/js/modulestest/modulestest.go b/js/modulestest/modulestest.go index 6106da9878f..039ec94ae39 100644 --- a/js/modulestest/modulestest.go +++ b/js/modulestest/modulestest.go @@ -3,7 +3,7 @@ package modulestest import ( "context" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/modules" "go.k6.io/k6/lib" @@ -17,7 +17,7 @@ type VU struct { InitEnvField *common.InitEnvironment EventsField common.Events StateField *lib.State - RuntimeField *goja.Runtime + RuntimeField *sobek.Runtime RegisterCallbackField func() func(f func() error) } @@ -44,7 +44,7 @@ func (m *VU) State() *lib.State { } // Runtime returns internally set field to conform to modules.VU interface -func (m *VU) Runtime() *goja.Runtime { +func (m *VU) Runtime() *sobek.Runtime { return m.RuntimeField } diff --git a/js/modulestest/runtime.go b/js/modulestest/runtime.go index 6ed91e72d57..99200f7d80d 100644 --- a/js/modulestest/runtime.go +++ b/js/modulestest/runtime.go @@ -6,7 +6,7 @@ import ( "net/url" "testing" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/js/compiler" "go.k6.io/k6/js/eventloop" @@ -33,7 +33,7 @@ func NewRuntime(t testing.TB) *Runtime { t.Cleanup(cancel) vu := &VU{ CtxField: ctx, - RuntimeField: goja.New(), + RuntimeField: sobek.New(), } vu.RuntimeField.SetFieldNameMapper(common.FieldNameMapper{}) vu.InitEnvField = &common.InitEnvironment{ @@ -100,7 +100,7 @@ func (r *Runtime) SetupModuleSystemFromAnother(another *Runtime) error { // `) // require.NoError(t, err) // } -func (r *Runtime) RunOnEventLoop(code string) (value goja.Value, err error) { +func (r *Runtime) RunOnEventLoop(code string) (value sobek.Value, err error) { defer r.EventLoop.WaitOnRegistered() err = r.EventLoop.Start(func() error { diff --git a/js/promises/promises.go b/js/promises/promises.go index 8dc53581aee..89cc463a444 100644 --- a/js/promises/promises.go +++ b/js/promises/promises.go @@ -2,7 +2,7 @@ package promises import ( - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/modules" ) @@ -14,7 +14,7 @@ import ( // // A typical usage would be: // -// func myAsynchronousFunc(vu modules.VU) *(goja.Promise) { +// func myAsynchronousFunc(vu modules.VU) *(sobek.Promise) { // promise, resolve, reject := promises.New(vu) // go func() { // v, err := someAsyncFunc() @@ -27,7 +27,7 @@ import ( // }() // return promise // } -func New(vu modules.VU) (p *goja.Promise, resolve func(result any), reject func(reason any)) { +func New(vu modules.VU) (p *sobek.Promise, resolve func(result any), reject func(reason any)) { p, resolveFunc, rejectFunc := vu.Runtime().NewPromise() callback := vu.RegisterCallback() diff --git a/js/runner.go b/js/runner.go index 70316e47e92..3c69fe74381 100644 --- a/js/runner.go +++ b/js/runner.go @@ -16,7 +16,7 @@ import ( "sync" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "github.com/sirupsen/logrus" "golang.org/x/net/http2" "golang.org/x/time/rate" @@ -288,7 +288,7 @@ func (r *Runner) Setup(ctx context.Context, out chan<- metrics.SampleContainer) return err } // r.setupData = nil is special it means undefined from this moment forward - if goja.IsUndefined(v) { + if sobek.IsUndefined(v) { r.setupData = nil return nil } @@ -330,7 +330,7 @@ func (r *Runner) Teardown(ctx context.Context, out chan<- metrics.SampleContaine return fmt.Errorf("error unmarshaling setup data for teardown() from JSON: %w", err) } } else { - data = goja.Undefined() + data = sobek.Undefined() } _, err := r.runPart(teardownCtx, out, consts.TeardownFn, data) return err @@ -374,10 +374,10 @@ func (r *Runner) HandleSummary(ctx context.Context, summary *lib.Summary) (map[s }() vu.moduleVUImpl.ctx = summaryCtx - callbackResult := goja.Undefined() + callbackResult := sobek.Undefined() fn := vu.getExported(consts.HandleSummaryFn) if fn != nil { - handleSummaryFn, ok := goja.AssertFunction(fn) + handleSummaryFn, ok := sobek.AssertFunction(fn) if !ok { return nil, fmt.Errorf("exported identifier %s must be a function", consts.HandleSummaryFn) } @@ -394,12 +394,12 @@ func (r *Runner) HandleSummary(ctx context.Context, summary *lib.Summary) (map[s if err != nil { return nil, fmt.Errorf("unexpected error while getting the summary wrapper: %w", err) } - handleSummaryWrapper, ok := goja.AssertFunction(handleSummaryWrapperRaw) + handleSummaryWrapper, ok := sobek.AssertFunction(handleSummaryWrapperRaw) if !ok { return nil, fmt.Errorf("unexpected error did not get a callable summary wrapper") } - wrapperArgs := []goja.Value{ + wrapperArgs := []sobek.Value{ callbackResult, vu.Runtime.ToValue(r.Bundle.preInitState.RuntimeOptions.SummaryExport.String), vu.Runtime.ToValue(summaryDataForJS), @@ -416,7 +416,7 @@ func (r *Runner) HandleSummary(ctx context.Context, summary *lib.Summary) (map[s return getSummaryResult(rawResult) } -func (r *Runner) checkDeadline(ctx context.Context, name string, result goja.Value, err error) error { +func (r *Runner) checkDeadline(ctx context.Context, name string, result sobek.Value, err error) error { if deadline, ok := ctx.Deadline(); !(ok && time.Now().After(deadline)) { return nil } @@ -424,7 +424,7 @@ func (r *Runner) checkDeadline(ctx context.Context, name string, result goja.Val // deadline is reached so we have timeouted but this might've not been registered correctly // we could have an error that is not context.Canceled in which case we should return it instead //nolint:errorlint - if err, ok := err.(*goja.InterruptedError); ok && result != nil && err.Value() != context.Canceled { + if err, ok := err.(*sobek.InterruptedError); ok && result != nil && err.Value() != context.Canceled { // TODO: silence this error? return err } @@ -527,17 +527,17 @@ func (r *Runner) runPart( out chan<- metrics.SampleContainer, name string, arg interface{}, -) (goja.Value, error) { +) (sobek.Value, error) { ctx, cancel := context.WithCancel(parentCtx) defer cancel() vu, err := r.newVU(ctx, 0, 0, out) if err != nil { - return goja.Undefined(), err + return sobek.Undefined(), err } - fn, ok := goja.AssertFunction(vu.getExported(name)) + fn, ok := sobek.AssertFunction(vu.getExported(name)) if !ok { - return goja.Undefined(), nil + return sobek.Undefined(), nil } go func() { @@ -548,7 +548,7 @@ func (r *Runner) runPart( groupPath, err := lib.NewGroupPath(lib.RootGroupPath, name) if err != nil { - return goja.Undefined(), err + return sobek.Undefined(), err } if r.Bundle.Options.SystemTags.Has(metrics.TagGroup) { @@ -566,13 +566,13 @@ func (r *Runner) runPart( } //nolint:gochecknoglobals -var gojaPromiseType = reflect.TypeOf((*goja.Promise)(nil)) +var gojaPromiseType = reflect.TypeOf((*sobek.Promise)(nil)) // unPromisify gets the result of v if it is a promise, otherwise returns v -func unPromisify(v goja.Value) goja.Value { +func unPromisify(v sobek.Value) sobek.Value { if !common.IsNullish(v) { if v.ExportType() == gojaPromiseType { - p, ok := v.Export().(*goja.Promise) + p, ok := v.Export().(*sobek.Promise) if !ok { panic("Something that was promise did not export to a promise; this shouldn't happen") } @@ -615,7 +615,7 @@ type VU struct { Samples chan<- metrics.SampleContainer - setupData goja.Value + setupData sobek.Value state *lib.State // count of iterations executed by this VU in each scenario @@ -745,7 +745,7 @@ func (u *ActiveVU) RunOnce() error { } u.setupData = u.Runtime.ToValue(data) } else { - u.setupData = goja.Undefined() + u.setupData = sobek.Undefined() } } @@ -775,7 +775,7 @@ func (u *ActiveVU) RunOnce() error { // Call the exported function. _, isFullIteration, totalTime, err := u.runFn(ctx, true, fn, cancel, u.setupData) if err != nil { - var x *goja.InterruptedError + var x *sobek.InterruptedError if errors.As(err, &x) { if v, ok := x.Value().(*errext.InterruptError); ok { v.Reason = x.Error() @@ -811,19 +811,19 @@ func (u *ActiveVU) emitAndWaitEvent(evt *event.Event) { } } -func (u *VU) getExported(name string) goja.Value { +func (u *VU) getExported(name string) sobek.Value { return u.BundleInstance.getExported(name) } // if isDefault is true, cancel also needs to be provided and it should cancel the provided context // TODO remove the need for the above through refactoring of this function and its callees func (u *VU) runFn( - ctx context.Context, isDefault bool, fn goja.Callable, cancel func(), args ...goja.Value, -) (v goja.Value, isFullIteration bool, t time.Duration, err error) { + ctx context.Context, isDefault bool, fn sobek.Callable, cancel func(), args ...sobek.Value, +) (v sobek.Value, isFullIteration bool, t time.Duration, err error) { if !u.Runner.Bundle.Options.NoCookiesReset.ValueOrZero() { u.state.CookieJar, err = cookiejar.New(nil) if err != nil { - return goja.Undefined(), false, time.Duration(0), err + return sobek.Undefined(), false, time.Duration(0), err } } @@ -842,7 +842,7 @@ func (u *VU) runFn( } err = common.RunWithPanicCatching(u.state.Logger, u.Runtime, func() error { return u.moduleVUImpl.eventLoop.Start(func() (err error) { - v, err = fn(goja.Undefined(), args...) // Actually run the JS script + v, err = fn(sobek.Undefined(), args...) // Actually run the JS script return err }) }) @@ -859,7 +859,7 @@ func (u *VU) runFn( u.moduleVUImpl.eventLoop.WaitOnRegistered() } endTime := time.Now() - var exception *goja.Exception + var exception *sobek.Exception if errors.As(err, &exception) { err = &scriptExceptionError{inner: exception} } @@ -893,7 +893,7 @@ func (u *ActiveVU) incrIteration() { } type scriptExceptionError struct { - inner *goja.Exception + inner *sobek.Exception } var _ interface { diff --git a/js/summary.go b/js/summary.go index d43a645987b..86dc34d18bc 100644 --- a/js/summary.go +++ b/js/summary.go @@ -7,7 +7,7 @@ import ( "io" "time" - "github.com/dop251/goja" + "github.com/grafana/sobek" "go.k6.io/k6/js/common" "go.k6.io/k6/lib" "go.k6.io/k6/metrics" @@ -104,7 +104,7 @@ func summarizeMetricsToObject(data *lib.Summary, options lib.Options, setupData return m } } else { - setupDataI = goja.Undefined() + setupDataI = sobek.Undefined() } m["setup_data"] = setupDataI @@ -138,8 +138,8 @@ func exportGroup(group *lib.Group) map[string]interface{} { } } -func getSummaryResult(rawResult goja.Value) (map[string]io.Reader, error) { - if goja.IsNull(rawResult) || goja.IsUndefined(rawResult) { +func getSummaryResult(rawResult sobek.Value) (map[string]io.Reader, error) { + if sobek.IsNull(rawResult) || sobek.IsUndefined(rawResult) { return nil, nil //nolint:nilnil // this is actually valid result in this case } diff --git a/js/tc39/tc39_test.go b/js/tc39/tc39_test.go index 56ab0419886..93f79d1090f 100644 --- a/js/tc39/tc39_test.go +++ b/js/tc39/tc39_test.go @@ -22,8 +22,8 @@ import ( "testing" "time" - "github.com/dop251/goja" "github.com/dop251/goja/parser" + "github.com/grafana/sobek" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.k6.io/k6/js/compiler" @@ -45,7 +45,7 @@ var ( // ignorableTestError = newSymbol(stringEmpty) - sabStub = goja.MustCompile("sabStub.js", ` + sabStub = sobek.MustCompile("sabStub.js", ` Object.defineProperty(this, "SharedArrayBuffer", { get: function() { throw IgnorableTestError; @@ -253,7 +253,7 @@ type tc39TestCtx struct { compilerPool *compiler.Pool base string t *testing.T - prgCache map[string]*goja.Program + prgCache map[string]*sobek.Program prgCacheLock sync.Mutex enableBench bool benchmark tc39BenchmarkData @@ -326,16 +326,16 @@ func parseTC39File(name string) (*tc39Meta, string, error) { return &meta, string(b), nil } -func (*tc39TestCtx) detachArrayBuffer(call goja.FunctionCall) goja.Value { - if obj, ok := call.Argument(0).(*goja.Object); ok { - var buf goja.ArrayBuffer - if goja.New().ExportTo(obj, &buf) == nil { - // if buf, ok := obj.Export().(goja.ArrayBuffer); ok { +func (*tc39TestCtx) detachArrayBuffer(call sobek.FunctionCall) sobek.Value { + if obj, ok := call.Argument(0).(*sobek.Object); ok { + var buf sobek.ArrayBuffer + if sobek.New().ExportTo(obj, &buf) == nil { + // if buf, ok := obj.Export().(sobek.ArrayBuffer); ok { buf.Detach() - return goja.Undefined() + return sobek.Undefined() } } - panic(goja.New().NewTypeError("detachArrayBuffer() is called with incompatible argument")) + panic(sobek.New().NewTypeError("detachArrayBuffer() is called with incompatible argument")) } func (ctx *tc39TestCtx) fail(t testing.TB, name string, strict bool, errStr string) { @@ -371,15 +371,15 @@ func (ctx *tc39TestCtx) runTC39Test(t testing.TB, name, src string, meta *tc39Me failf("panic while running %s: %v", name, x) } }() - vm := goja.New() + vm := sobek.New() _262 := vm.NewObject() ignorableTestError := vm.NewGoError(fmt.Errorf("")) _ = vm.Set("IgnorableTestError", ignorableTestError) _ = _262.Set("detachArrayBuffer", ctx.detachArrayBuffer) - _ = _262.Set("createRealm", func(goja.FunctionCall) goja.Value { + _ = _262.Set("createRealm", func(sobek.FunctionCall) sobek.Value { panic(ignorableTestError) }) - _ = _262.Set("evalScript", func(call goja.FunctionCall) goja.Value { + _ = _262.Set("evalScript", func(call sobek.FunctionCall) sobek.Value { script := call.Argument(0).String() result, err := vm.RunString(script) if err != nil { @@ -432,7 +432,7 @@ func (ctx *tc39TestCtx) runTC39Test(t testing.TB, name, src string, meta *tc39Me } if meta.Negative.Type == "" { - if err, ok := err.(*goja.Exception); ok { //nolint:errorlint + if err, ok := err.(*sobek.Exception); ok { //nolint:errorlint if err.Value() == ignorableTestError { t.Skip("Test threw IgnorableTestError") } @@ -484,10 +484,10 @@ func (ctx *tc39TestCtx) runTC39Test(t testing.TB, name, src string, meta *tc39Me func getErrType(name string, err error, failf func(str string, args ...interface{})) string { switch err := err.(type) { //nolint:errorlint - case *goja.Exception: - if o, ok := err.Value().(*goja.Object); ok { + case *sobek.Exception: + if o, ok := err.Value().(*sobek.Object); ok { if c := o.Get("constructor"); c != nil { - if c, ok := c.(*goja.Object); ok { + if c, ok := c.(*sobek.Object); ok { return c.Get("name").String() } failf("%s: error constructor is not an object (%v)", name, o) @@ -498,9 +498,9 @@ func getErrType(name string, err error, failf func(str string, args ...interface } failf("%s: error is not an object (%v)", name, err.Value()) return "" - case *goja.CompilerSyntaxError, *parser.Error, parser.ErrorList: + case *sobek.CompilerSyntaxError, *parser.Error, parser.ErrorList: return "SyntaxError" - case *goja.CompilerReferenceError: + case *sobek.CompilerReferenceError: return "ReferenceError" default: failf("%s: error is not a JS error: %v", name, err) @@ -570,7 +570,7 @@ func breakingTestErrorsFilename(compatibilityMode lib.CompatibilityMode) string } func (ctx *tc39TestCtx) init() { - ctx.prgCache = make(map[string]*goja.Program) + ctx.prgCache = make(map[string]*sobek.Program) ctx.errors = make(map[string]string) if !*update { @@ -589,7 +589,7 @@ func (ctx *tc39TestCtx) init() { } } -func (ctx *tc39TestCtx) compile(base, name string) (*goja.Program, error) { +func (ctx *tc39TestCtx) compile(base, name string) (*sobek.Program, error) { ctx.prgCacheLock.Lock() defer ctx.prgCacheLock.Unlock() @@ -621,7 +621,7 @@ func (ctx *tc39TestCtx) compile(base, name string) (*goja.Program, error) { return prg, nil } -func (ctx *tc39TestCtx) runFile(base, name string, vm *goja.Runtime) error { +func (ctx *tc39TestCtx) runFile(base, name string, vm *sobek.Runtime) error { prg, err := ctx.compile(base, name) if err != nil { return err @@ -630,7 +630,7 @@ func (ctx *tc39TestCtx) runFile(base, name string, vm *goja.Runtime) error { return err } -func (ctx *tc39TestCtx) runTC39Script(name, src string, includes []string, vm *goja.Runtime, expectsError bool) (early bool, origErr, err error) { +func (ctx *tc39TestCtx) runTC39Script(name, src string, includes []string, vm *sobek.Runtime, expectsError bool) (early bool, origErr, err error) { early = true err = ctx.runFile(ctx.base, path.Join("harness", "assert.js"), vm) if err != nil { @@ -649,7 +649,7 @@ func (ctx *tc39TestCtx) runTC39Script(name, src string, includes []string, vm *g } } - var p *goja.Program + var p *sobek.Program comp := ctx.compilerPool.Get() defer ctx.compilerPool.Put(comp) comp.Options = compiler.Options{Strict: false, CompatibilityMode: lib.CompatibilityModeBase} @@ -670,7 +670,7 @@ func (ctx *tc39TestCtx) runTC39Script(name, src string, includes []string, vm *g return early, origErr, err } -func (ctx *tc39TestCtx) runTC39Module(name, src string, includes []string, vm *goja.Runtime) (early bool, origErr, err error) { +func (ctx *tc39TestCtx) runTC39Module(name, src string, includes []string, vm *sobek.Runtime) (early bool, origErr, err error) { currentFS := os.DirFS(".") if err != nil { panic(err) diff --git a/vendor/github.com/dop251/goja/README.md b/vendor/github.com/dop251/goja/README.md index 3ad93dac3dc..a4d0c09be11 100644 --- a/vendor/github.com/dop251/goja/README.md +++ b/vendor/github.com/dop251/goja/README.md @@ -10,7 +10,7 @@ performance. This project was largely inspired by [otto](https://github.com/robertkrimen/otto). -Minimum required Go version is 1.16. +The minimum required Go version is 1.20. Features -------- diff --git a/vendor/github.com/dop251/goja/compiler.go b/vendor/github.com/dop251/goja/compiler.go index 967b0a050a2..2abd9ba528b 100644 --- a/vendor/github.com/dop251/goja/compiler.go +++ b/vendor/github.com/dop251/goja/compiler.go @@ -67,8 +67,7 @@ type srcMapItem struct { // This representation is not linked to a runtime in any way and can be used concurrently. // It is always preferable to use a Program over a string when running code as it skips the compilation step. type Program struct { - code []instruction - values []Value + code []instruction funcName unistring.String src *file.File @@ -88,6 +87,8 @@ type compiler struct { ctxVM *vm // VM in which an eval() code is compiled codeScratchpad []instruction + + stringCache map[unistring.String]Value } type binding struct { @@ -384,6 +385,29 @@ func (c *compiler) popScope() { c.scope = c.scope.outer } +func (c *compiler) emitLiteralString(s String) { + key := s.string() + if c.stringCache == nil { + c.stringCache = make(map[unistring.String]Value) + } + internVal := c.stringCache[key] + if internVal == nil { + c.stringCache[key] = s + internVal = s + } + + c.emit(loadVal{internVal}) +} + +func (c *compiler) emitLiteralValue(v Value) { + if s, ok := v.(String); ok { + c.emitLiteralString(s) + return + } + + c.emit(loadVal{v}) +} + func newCompiler() *compiler { c := &compiler{ p: &Program{}, @@ -394,23 +418,11 @@ func newCompiler() *compiler { return c } -func (p *Program) defineLiteralValue(val Value) uint32 { - for idx, v := range p.values { - if v.SameAs(val) { - return uint32(idx) - } - } - idx := uint32(len(p.values)) - p.values = append(p.values, val) - return idx -} - func (p *Program) dumpCode(logger func(format string, args ...interface{})) { p._dumpCode("", logger) } func (p *Program) _dumpCode(indent string, logger func(format string, args ...interface{})) { - logger("values: %+v", p.values) dumpInitFields := func(initFields *Program) { i := indent + ">" logger("%s ---- init_fields:", i) @@ -982,6 +994,7 @@ func (c *compiler) compile(in *ast.Program, strict, inGlobal bool, evalVm *vm) { } scope.finaliseVarAlloc(0) + c.stringCache = nil } func (c *compiler) compileDeclList(v []*ast.VariableDeclaration, inFunc bool) { diff --git a/vendor/github.com/dop251/goja/compiler_expr.go b/vendor/github.com/dop251/goja/compiler_expr.go index b4e39898f22..477580aecf6 100644 --- a/vendor/github.com/dop251/goja/compiler_expr.go +++ b/vendor/github.com/dop251/goja/compiler_expr.go @@ -234,7 +234,7 @@ type compiledOptional struct { func (e *defaultDeleteExpr) emitGetter(putOnStack bool) { e.expr.emitGetter(false) if putOnStack { - e.c.emit(loadVal(e.c.p.defineLiteralValue(valueTrue))) + e.c.emitLiteralValue(valueTrue) } } @@ -373,7 +373,7 @@ func (e *baseCompiledExpr) addSrcMap() { func (e *constantExpr) emitGetter(putOnStack bool) { if putOnStack { e.addSrcMap() - e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) + e.c.emitLiteralValue(e.val) } } @@ -1261,7 +1261,7 @@ func (e *compiledAssignExpr) emitGetter(putOnStack bool) { func (e *compiledLiteral) emitGetter(putOnStack bool) { if putOnStack { - e.c.emit(loadVal(e.c.p.defineLiteralValue(e.val))) + e.c.emitLiteralValue(e.val) } } @@ -1272,15 +1272,15 @@ func (e *compiledLiteral) constant() bool { func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) { if e.tag == nil { if len(e.elements) == 0 { - e.c.emit(loadVal(e.c.p.defineLiteralValue(stringEmpty))) + e.c.emitLiteralString(stringEmpty) } else { tail := e.elements[len(e.elements)-1].Parsed if len(e.elements) == 1 { - e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) + e.c.emitLiteralString(stringValueFromRaw(tail)) } else { stringCount := 0 if head := e.elements[0].Parsed; head != "" { - e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(head)))) + e.c.emitLiteralString(stringValueFromRaw(head)) stringCount++ } e.expressions[0].emitGetter(true) @@ -1288,7 +1288,7 @@ func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) { stringCount++ for i := 1; i < len(e.elements)-1; i++ { if elt := e.elements[i].Parsed; elt != "" { - e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(elt)))) + e.c.emitLiteralString(stringValueFromRaw(elt)) stringCount++ } e.expressions[i].emitGetter(true) @@ -1296,7 +1296,7 @@ func (e *compiledTemplateLiteral) emitGetter(putOnStack bool) { stringCount++ } if tail != "" { - e.c.emit(loadVal(e.c.p.defineLiteralValue(stringValueFromRaw(tail)))) + e.c.emitLiteralString(stringValueFromRaw(tail)) stringCount++ } e.c.emit(concatStrings(stringCount)) @@ -2450,7 +2450,7 @@ func (c *compiler) emitThrow(v Value) { c.emit(loadDynamic(t)) msg := o.self.getStr("message", nil) if msg != nil { - c.emit(loadVal(c.p.defineLiteralValue(msg))) + c.emitLiteralValue(msg) c.emit(_new(1)) } else { c.emit(_new(0)) @@ -2467,7 +2467,7 @@ func (c *compiler) emitConst(expr compiledExpr, putOnStack bool) { v, ex := c.evalConst(expr) if ex == nil { if putOnStack { - c.emit(loadVal(c.p.defineLiteralValue(v))) + c.emitLiteralValue(v) } } else { c.emitThrow(ex.val) @@ -2633,7 +2633,7 @@ func (e *compiledLogicalOr) emitGetter(putOnStack bool) { e.c.emitExpr(e.right, putOnStack) } else { if putOnStack { - e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) + e.c.emitLiteralValue(v) } } } else { @@ -2674,7 +2674,7 @@ func (e *compiledCoalesce) emitGetter(putOnStack bool) { e.c.emitExpr(e.right, putOnStack) } else { if putOnStack { - e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) + e.c.emitLiteralValue(v) } } } else { @@ -2714,7 +2714,7 @@ func (e *compiledLogicalAnd) emitGetter(putOnStack bool) { if e.left.constant() { if v, ex := e.c.evalConst(e.left); ex == nil { if !v.ToBoolean() { - e.c.emit(loadVal(e.c.p.defineLiteralValue(v))) + e.c.emitLiteralValue(v) } else { e.c.emitExpr(e.right, putOnStack) } diff --git a/vendor/github.com/dop251/goja/vm.go b/vendor/github.com/dop251/goja/vm.go index 29fffbebebf..30b79331628 100644 --- a/vendor/github.com/dop251/goja/vm.go +++ b/vendor/github.com/dop251/goja/vm.go @@ -897,10 +897,12 @@ func (vm *vm) toCallee(v Value) *Object { panic(vm.r.NewTypeError("Value is not an object: %s", v.toString())) } -type loadVal uint32 +type loadVal struct { + v Value +} func (l loadVal) exec(vm *vm) { - vm.push(vm.prg.values[l]) + vm.push(l.v) vm.pc++ } diff --git a/vendor/github.com/grafana/sobek/LICENSE b/vendor/github.com/grafana/sobek/LICENSE new file mode 100644 index 00000000000..09c000454f7 --- /dev/null +++ b/vendor/github.com/grafana/sobek/LICENSE @@ -0,0 +1,15 @@ +Copyright (c) 2016 Dmitry Panov + +Copyright (c) 2012 Robert Krimen + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/grafana/sobek/README.md b/vendor/github.com/grafana/sobek/README.md new file mode 100644 index 00000000000..51d78207ef6 --- /dev/null +++ b/vendor/github.com/grafana/sobek/README.md @@ -0,0 +1,7 @@ +## Sobek + +Is a fork of [goja](https://github.com/dop251/goja) named after the [ancient Egyptian god](https://en.wikipedia.org/wiki/Sobek) of the same name + +The fork is currently just aliasing types in order to facilitate the moving of the current k6 codebase and extension to it with less friction. + +The plan and discussion on the transition can be find in [this issue](https://github.com/grafana/k6/issues/3773). diff --git a/vendor/github.com/grafana/sobek/aliases.go b/vendor/github.com/grafana/sobek/aliases.go new file mode 100644 index 00000000000..6390b40360f --- /dev/null +++ b/vendor/github.com/grafana/sobek/aliases.go @@ -0,0 +1,128 @@ +package sobek + +import ( + "github.com/dop251/goja" + "github.com/dop251/goja/ast" + "github.com/dop251/goja/parser" +) + +const ( + FLAG_NOT_SET Flag = iota + FLAG_FALSE + FLAG_TRUE +) + +func Null() Value { return goja.Null() } + +func IsInfinity(v Value) bool { return goja.IsInfinity(v) } + +func IsNaN(v Value) bool { return goja.IsNaN(v) } + +func IsNull(v Value) bool { return goja.IsNull(v) } + +func IsUndefined(v Value) bool { return goja.IsUndefined(v) } + +func Parse(name, src string, options ...parser.Option) (prg *ast.Program, err error) { + return goja.Parse(name, src, options...) +} + +func AssertFunction(v Value) (Callable, bool) { return goja.AssertFunction(v) } + +func AssertConstructor(v Value) (Constructor, bool) { return goja.AssertConstructor(v) } + +func Undefined() Value { return goja.Undefined() } + +func CompileAST(prg *ast.Program, strict bool) (*Program, error) { + return goja.CompileAST(prg, strict) +} + +func Compile(name, src string, strict bool) (*Program, error) { + return goja.Compile(name, src, strict) +} + +func MustCompile(name, src string, strict bool) *Program { + return goja.MustCompile(name, src, strict) +} + +func New() *Runtime { + return goja.New() +} + +type ArrayBuffer = goja.ArrayBuffer + +type ( + AsyncContextTracker = goja.AsyncContextTracker + Callable = goja.Callable +) + +type ( + CompilerError = goja.CompilerError + CompilerReferenceError = goja.CompilerReferenceError +) + +type CompilerSyntaxError = goja.CompilerSyntaxError + +type Constructor = goja.Constructor + +type ConstructorCall = goja.ConstructorCall + +type ( + DynamicArray = goja.DynamicArray + DynamicObject = goja.DynamicObject + Exception = goja.Exception +) + +type FieldNameMapper = goja.FieldNameMapper + +type ( + Flag = goja.Flag + FunctionCall = goja.FunctionCall +) + +type InterruptedError = goja.InterruptedError + +type ( + JsonEncodable = goja.JsonEncodable + Now = goja.Now + Object = goja.Object +) + +type Program = goja.Program + +type Promise = goja.Promise + +type ( + PromiseRejectionOperation = goja.PromiseRejectionOperation + PromiseRejectionTracker = goja.PromiseRejectionTracker + PromiseState = goja.PromiseState + PropertyDescriptor = goja.PropertyDescriptor +) + +const ( + PromiseRejectionReject PromiseRejectionOperation = iota + PromiseRejectionHandle +) + +const ( + PromiseStatePending PromiseState = iota + PromiseStateFulfilled + PromiseStateRejected +) + +type Proxy = goja.Proxy + +type ( + ProxyTrapConfig = goja.ProxyTrapConfig + RandSource = goja.RandSource + Runtime = goja.Runtime +) + +type StackFrame = goja.StackFrame + +type ( + StackOverflowError = goja.StackOverflowError + String = goja.String + StringBuilder = goja.StringBuilder + Symbol = goja.Symbol + Value = goja.Value +) diff --git a/vendor/modules.txt b/vendor/modules.txt index 933f6be974e..b4a260efc6b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -105,8 +105,8 @@ github.com/dgryski/go-rendezvous ## explicit; go 1.13 github.com/dlclark/regexp2 github.com/dlclark/regexp2/syntax -# github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 -## explicit; go 1.16 +# github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2 +## explicit; go 1.20 github.com/dop251/goja github.com/dop251/goja/ast github.com/dop251/goja/file @@ -173,6 +173,9 @@ github.com/google/uuid # github.com/gorilla/websocket v1.5.1 ## explicit; go 1.20 github.com/gorilla/websocket +# github.com/grafana/sobek v0.0.0-20240606091932-2da0e9e5f3e7 +## explicit; go 1.20 +github.com/grafana/sobek # github.com/grafana/xk6-browser v1.5.1 ## explicit; go 1.20 github.com/grafana/xk6-browser/browser