From 82a0328b05f9d7253b8c4ff573ec06b9c4342650 Mon Sep 17 00:00:00 2001 From: sg Date: Mon, 2 Sep 2024 20:27:56 +0100 Subject: [PATCH] dependencies, update playwright-go --- go.mod | 24 +- go.sum | 63 +- .../github.com/danwakefield/fnmatch/LICENSE | 23 - .../github.com/danwakefield/fnmatch/README.md | 4 - .../danwakefield/fnmatch/fnmatch.go | 219 - .../golang-set/v2}/.gitignore | 3 +- .../github.com/deckarep/golang-set/v2/LICENSE | 22 + .../deckarep/golang-set/v2/README.md | 181 + .../deckarep/golang-set/v2/iterator.go | 58 + .../deckarep/golang-set/v2/new_improved.jpeg | Bin 0 -> 120935 bytes .../github.com/deckarep/golang-set/v2/set.go | 255 + .../deckarep/golang-set/v2/sorted.go | 42 + .../deckarep/golang-set/v2/threadsafe.go | 299 + .../deckarep/golang-set/v2/threadunsafe.go | 330 + .../go-jose/go-jose/v3/json/decode.go | 3 +- .../go-jose/go-jose/v3/json/encode.go | 28 +- .../go-jose/go-jose/v3/json/stream.go | 1 - .../playwright-go/.gitignore | 4 +- .../playwright-go/.golangci.yaml | 6 + .../playwright-go/CONTRIBUTING.md | 3 + .../playwright-go/Dockerfile.example | 25 + .../playwright-go/README.md | 12 +- .../playwright-go/artifact.go | 14 +- .../playwright-go/assertions.go | 7 +- .../playwright-go/binding_call.go | 25 +- .../playwright-go/browser.go | 92 +- .../playwright-go/browser_context.go | 278 +- .../playwright-go/browser_type.go | 40 +- .../playwright-go/channel.go | 15 +- .../playwright-go/channel_owner.go | 5 +- .../playwright-go/clock.go | 111 + .../playwright-go/connection.go | 130 +- .../playwright-go/element_handle.go | 35 +- .../playwright-go/errors.go | 43 +- .../playwright-go/event_emitter.go | 156 +- .../playwright-go/fetch.go | 44 +- .../playwright-go/file_chooser.go | 2 +- .../playwright-go/frame.go | 52 +- .../playwright-go/frame_locator.go | 4 + .../playwright-go/generated-enums.go | 34 +- .../playwright-go/generated-interfaces.go | 593 +- .../playwright-go/generated-structs.go | 634 +- .../playwright-go/glob.go | 92 + .../playwright-go/har_router.go | 9 +- .../playwright-go/helpers.go | 215 +- .../playwright-go/input_files_helper.go | 202 + .../internal/multierror/multierror_g0120.go | 4 +- .../internal/multierror/multierror_go119.go | 4 +- .../playwright-go/internal/safe/map.go | 91 + .../playwright-go/js_handle.go | 145 +- .../playwright-go/jsonPipe.go | 43 +- .../playwright-go/local_utils.go | 16 +- .../playwright-go/locator.go | 17 +- .../playwright-go/locator_assertions.go | 119 +- .../playwright-go/objectFactory.go | 2 +- .../playwright-go/page.go | 305 +- .../playwright-go/page_assertions.go | 12 +- .../playwright-go/request.go | 37 +- .../playwright-go/response.go | 9 +- .../playwright-go/route.go | 67 +- .../playwright-community/playwright-go/run.go | 252 +- .../playwright-go/run_unix.go | 3 + .../playwright-go/run_win.go | 3 + .../playwright-go/stream.go | 4 +- .../playwright-go/tracing.go | 18 +- .../playwright-go/transport.go | 140 +- .../playwright-go/type_helpers.go | 25 + .../playwright-go/video.go | 31 +- .../playwright-go/waiter.go | 5 +- .../playwright-go/web_error.go | 4 +- .../playwright-go/websocket.go | 7 +- .../playwright-go/writable_stream.go | 44 + .../x/crypto/chacha20/chacha_ppc64le.s | 110 +- .../x/crypto/internal/poly1305/sum_ppc64le.s | 14 +- vendor/golang.org/x/crypto/ocsp/ocsp.go | 13 +- vendor/golang.org/x/exp/slices/cmp.go | 44 + vendor/golang.org/x/exp/slices/slices.go | 389 +- vendor/golang.org/x/exp/slices/sort.go | 115 +- .../slices/{zsortfunc.go => zsortanyfunc.go} | 154 +- .../golang.org/x/exp/slices/zsortordered.go | 34 +- .../golang.org/x/net/http/httpguts/httplex.go | 13 +- vendor/golang.org/x/net/http2/frame.go | 51 +- vendor/golang.org/x/net/http2/pipe.go | 11 +- vendor/golang.org/x/net/http2/server.go | 24 +- vendor/golang.org/x/net/http2/testsync.go | 331 + vendor/golang.org/x/net/http2/transport.go | 322 +- .../golang.org/x/sync/semaphore/semaphore.go | 42 +- vendor/golang.org/x/sys/cpu/cpu.go | 1 + vendor/golang.org/x/sys/cpu/cpu_arm64.go | 10 + vendor/golang.org/x/sys/cpu/cpu_arm64.s | 8 + vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 1 + .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 5 + vendor/golang.org/x/sys/unix/aliases.go | 2 +- vendor/golang.org/x/sys/unix/asm_zos_s390x.s | 665 +- vendor/golang.org/x/sys/unix/bpxsvc_zos.go | 657 + vendor/golang.org/x/sys/unix/bpxsvc_zos.s | 192 + vendor/golang.org/x/sys/unix/epoll_zos.go | 220 - vendor/golang.org/x/sys/unix/fstatfs_zos.go | 163 - vendor/golang.org/x/sys/unix/mkerrors.sh | 2 +- vendor/golang.org/x/sys/unix/mmap_nomremap.go | 2 +- vendor/golang.org/x/sys/unix/pagesize_unix.go | 2 +- .../x/sys/unix/readdirent_getdirentries.go | 2 +- vendor/golang.org/x/sys/unix/sockcmsg_zos.go | 58 + .../golang.org/x/sys/unix/symaddr_zos_s390x.s | 75 + .../x/sys/unix/syscall_darwin_libSystem.go | 2 +- .../golang.org/x/sys/unix/syscall_freebsd.go | 12 +- vendor/golang.org/x/sys/unix/syscall_linux.go | 99 + .../x/sys/unix/syscall_zos_s390x.go | 1509 +- vendor/golang.org/x/sys/unix/sysvshm_unix.go | 2 +- .../x/sys/unix/sysvshm_unix_other.go | 2 +- vendor/golang.org/x/sys/unix/zerrors_linux.go | 45 +- .../x/sys/unix/zerrors_linux_386.go | 3 + .../x/sys/unix/zerrors_linux_amd64.go | 3 + .../x/sys/unix/zerrors_linux_arm.go | 3 + .../x/sys/unix/zerrors_linux_arm64.go | 3 + .../x/sys/unix/zerrors_linux_loong64.go | 3 + .../x/sys/unix/zerrors_linux_mips.go | 3 + .../x/sys/unix/zerrors_linux_mips64.go | 3 + .../x/sys/unix/zerrors_linux_mips64le.go | 3 + .../x/sys/unix/zerrors_linux_mipsle.go | 3 + .../x/sys/unix/zerrors_linux_ppc.go | 3 + .../x/sys/unix/zerrors_linux_ppc64.go | 3 + .../x/sys/unix/zerrors_linux_ppc64le.go | 3 + .../x/sys/unix/zerrors_linux_riscv64.go | 3 + .../x/sys/unix/zerrors_linux_s390x.go | 3 + .../x/sys/unix/zerrors_linux_sparc64.go | 3 + .../x/sys/unix/zerrors_zos_s390x.go | 233 +- .../x/sys/unix/zsymaddr_zos_s390x.s | 364 + .../golang.org/x/sys/unix/zsyscall_linux.go | 10 + .../x/sys/unix/zsyscall_zos_s390x.go | 3113 ++- .../x/sys/unix/zsysnum_linux_386.go | 9 + .../x/sys/unix/zsysnum_linux_amd64.go | 8 + .../x/sys/unix/zsysnum_linux_arm.go | 9 + .../x/sys/unix/zsysnum_linux_arm64.go | 9 + .../x/sys/unix/zsysnum_linux_loong64.go | 9 + .../x/sys/unix/zsysnum_linux_mips.go | 9 + .../x/sys/unix/zsysnum_linux_mips64.go | 9 + .../x/sys/unix/zsysnum_linux_mips64le.go | 9 + .../x/sys/unix/zsysnum_linux_mipsle.go | 9 + .../x/sys/unix/zsysnum_linux_ppc.go | 9 + .../x/sys/unix/zsysnum_linux_ppc64.go | 9 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 9 + .../x/sys/unix/zsysnum_linux_riscv64.go | 9 + .../x/sys/unix/zsysnum_linux_s390x.go | 9 + .../x/sys/unix/zsysnum_linux_sparc64.go | 9 + .../x/sys/unix/zsysnum_zos_s390x.go | 5507 ++--- vendor/golang.org/x/sys/unix/ztypes_linux.go | 209 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 8 - .../x/sys/unix/ztypes_linux_amd64.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 9 - .../x/sys/unix/ztypes_linux_arm64.go | 9 - .../x/sys/unix/ztypes_linux_loong64.go | 9 - .../x/sys/unix/ztypes_linux_mips.go | 9 - .../x/sys/unix/ztypes_linux_mips64.go | 9 - .../x/sys/unix/ztypes_linux_mips64le.go | 9 - .../x/sys/unix/ztypes_linux_mipsle.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 9 - .../x/sys/unix/ztypes_linux_ppc64.go | 9 - .../x/sys/unix/ztypes_linux_ppc64le.go | 9 - .../x/sys/unix/ztypes_linux_riscv64.go | 9 - .../x/sys/unix/ztypes_linux_s390x.go | 9 - .../x/sys/unix/ztypes_linux_sparc64.go | 9 - .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 146 +- vendor/golang.org/x/sys/windows/aliases.go | 2 +- vendor/golang.org/x/sys/windows/empty.s | 8 - .../golang.org/x/sys/windows/env_windows.go | 17 +- .../x/sys/windows/syscall_windows.go | 85 +- .../golang.org/x/sys/windows/types_windows.go | 24 + .../x/sys/windows/zsyscall_windows.go | 126 +- .../x/tools/cmd/goimports/goimports_gc.go | 2 +- .../x/tools/go/gcexportdata/gcexportdata.go | 2 +- vendor/golang.org/x/tools/go/packages/doc.go | 40 +- .../x/tools/go/packages/external.go | 77 +- .../golang.org/x/tools/go/packages/golist.go | 35 +- .../x/tools/go/packages/packages.go | 204 +- .../x/tools/go/types/objectpath/objectpath.go | 23 +- .../x/tools/internal/aliases/aliases.go | 32 + .../x/tools/internal/aliases/aliases_go121.go | 31 + .../x/tools/internal/aliases/aliases_go122.go | 63 + .../x/tools/internal/event/tag/tag.go | 59 - .../x/tools/internal/gcimporter/gcimporter.go | 7 - .../x/tools/internal/gcimporter/iexport.go | 35 +- .../x/tools/internal/gcimporter/iimport.go | 80 +- .../internal/gcimporter/support_go117.go | 16 - .../internal/gcimporter/support_go118.go | 3 - .../x/tools/internal/gcimporter/unified_no.go | 4 +- .../tools/internal/gcimporter/unified_yes.go | 4 +- .../x/tools/internal/gcimporter/ureader_no.go | 19 - .../tools/internal/gcimporter/ureader_yes.go | 10 +- .../x/tools/internal/gocommand/invoke.go | 13 +- .../x/tools/internal/gocommand/vendor.go | 54 + .../x/tools/internal/gopathwalk/walk.go | 308 +- .../x/tools/internal/imports/fix.go | 259 +- .../x/tools/internal/imports/imports.go | 6 +- .../x/tools/internal/imports/mod.go | 348 +- .../x/tools/internal/imports/mod_cache.go | 119 +- .../x/tools/internal/imports/sortimports.go | 2 +- .../x/tools/internal/imports/zstdlib.go | 11345 ---------- .../x/tools/internal/pkgbits/decoder.go | 4 + .../x/tools/internal/stdlib/manifest.go | 17320 ++++++++++++++++ .../x/tools/internal/stdlib/stdlib.go | 97 + .../internal/tokeninternal/tokeninternal.go | 28 +- .../x/tools/internal/typeparams/common.go | 204 - .../x/tools/internal/typeparams/coretype.go | 122 - .../x/tools/internal/typeparams/normalize.go | 218 - .../x/tools/internal/typeparams/termlist.go | 163 - .../x/tools/internal/typeparams/typeterm.go | 169 - .../tools/internal/typesinternal/errorcode.go | 6 +- .../x/tools/internal/typesinternal/recv.go | 43 + .../x/tools/internal/typesinternal/toonew.go | 89 + .../x/tools/internal/typesinternal/types.go | 2 - .../tools/internal/typesinternal/types_118.go | 19 - .../x/tools/internal/versions/features.go | 43 + .../x/tools/internal/versions/toolchain.go | 14 + .../internal/versions/toolchain_go119.go | 14 + .../internal/versions/toolchain_go120.go | 14 + .../internal/versions/toolchain_go121.go | 14 + .../x/tools/internal/versions/types_go121.go | 18 +- .../x/tools/internal/versions/types_go122.go | 25 +- .../{versions_go121.go => versions.go} | 14 +- .../tools/internal/versions/versions_go122.go | 38 - vendor/modules.txt | 35 +- 222 files changed, 34185 insertions(+), 19132 deletions(-) delete mode 100644 vendor/github.com/danwakefield/fnmatch/LICENSE delete mode 100644 vendor/github.com/danwakefield/fnmatch/README.md delete mode 100644 vendor/github.com/danwakefield/fnmatch/fnmatch.go rename vendor/github.com/{danwakefield/fnmatch => deckarep/golang-set/v2}/.gitignore (94%) create mode 100644 vendor/github.com/deckarep/golang-set/v2/LICENSE create mode 100644 vendor/github.com/deckarep/golang-set/v2/README.md create mode 100644 vendor/github.com/deckarep/golang-set/v2/iterator.go create mode 100644 vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg create mode 100644 vendor/github.com/deckarep/golang-set/v2/set.go create mode 100644 vendor/github.com/deckarep/golang-set/v2/sorted.go create mode 100644 vendor/github.com/deckarep/golang-set/v2/threadsafe.go create mode 100644 vendor/github.com/deckarep/golang-set/v2/threadunsafe.go create mode 100644 vendor/github.com/playwright-community/playwright-go/.golangci.yaml create mode 100644 vendor/github.com/playwright-community/playwright-go/Dockerfile.example create mode 100644 vendor/github.com/playwright-community/playwright-go/clock.go create mode 100644 vendor/github.com/playwright-community/playwright-go/glob.go create mode 100644 vendor/github.com/playwright-community/playwright-go/input_files_helper.go create mode 100644 vendor/github.com/playwright-community/playwright-go/internal/safe/map.go create mode 100644 vendor/github.com/playwright-community/playwright-go/writable_stream.go create mode 100644 vendor/golang.org/x/exp/slices/cmp.go rename vendor/golang.org/x/exp/slices/{zsortfunc.go => zsortanyfunc.go} (64%) create mode 100644 vendor/golang.org/x/net/http2/testsync.go create mode 100644 vendor/golang.org/x/sys/unix/bpxsvc_zos.go create mode 100644 vendor/golang.org/x/sys/unix/bpxsvc_zos.s delete mode 100644 vendor/golang.org/x/sys/unix/epoll_zos.go delete mode 100644 vendor/golang.org/x/sys/unix/fstatfs_zos.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_zos.go create mode 100644 vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s create mode 100644 vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s delete mode 100644 vendor/golang.org/x/sys/windows/empty.s create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go121.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go122.go delete mode 100644 vendor/golang.org/x/tools/internal/event/tag/tag.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support_go117.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go delete mode 100644 vendor/golang.org/x/tools/internal/imports/zstdlib.go create mode 100644 vendor/golang.org/x/tools/internal/stdlib/manifest.go create mode 100644 vendor/golang.org/x/tools/internal/stdlib/stdlib.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/common.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/coretype.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/normalize.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/termlist.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeterm.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/recv.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/toonew.go delete mode 100644 vendor/golang.org/x/tools/internal/typesinternal/types_118.go create mode 100644 vendor/golang.org/x/tools/internal/versions/features.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go119.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go120.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go121.go rename vendor/golang.org/x/tools/internal/versions/{versions_go121.go => versions.go} (77%) delete mode 100644 vendor/golang.org/x/tools/internal/versions/versions_go122.go diff --git a/go.mod b/go.mod index 3de12f9b7..1776a0bd8 100644 --- a/go.mod +++ b/go.mod @@ -21,16 +21,16 @@ require ( github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 github.com/owenrumney/go-sarif/v2 v2.1.2 github.com/package-url/packageurl-go v0.1.0 - github.com/playwright-community/playwright-go v0.3900.1 + github.com/playwright-community/playwright-go v0.4702.0 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.11.0 github.com/stretchr/testify v1.9.0 github.com/tektoncd/pipeline v0.57.0 github.com/trivago/tgo v1.0.7 go.mongodb.org/mongo-driver v1.10.0 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.23.0 golang.org/x/oauth2 v0.16.0 - golang.org/x/sync v0.6.0 + golang.org/x/sync v0.7.0 google.golang.org/api v0.156.0 google.golang.org/protobuf v1.35.1 helm.sh/helm/v3 v3.14.4 @@ -61,12 +61,12 @@ require ( github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect - github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-jose/go-jose/v3 v3.0.1 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/logr v1.4.1 // indirect @@ -140,12 +140,12 @@ require ( go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/term v0.20.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.16.1 // indirect + golang.org/x/tools v0.21.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect @@ -190,8 +190,8 @@ require ( github.com/spf13/pflag v1.0.5 github.com/subosito/gotenv v1.2.0 // indirect go.uber.org/atomic v1.10.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e2791a016..d4d985002 100644 --- a/go.sum +++ b/go.sum @@ -350,12 +350,12 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= -github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk= 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/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4= +github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= +github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -445,8 +445,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= -github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -891,6 +891,8 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -1007,8 +1009,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/playwright-community/playwright-go v0.3900.1 h1:8BkmDxVzLTp3USQ50EyXJSXcz0XDMwNP5y29lHIZ9Fc= -github.com/playwright-community/playwright-go v0.3900.1/go.mod h1:mbNzMqt04IVRdhVfXWqmCxd81gCdL3BA5hj6/pVAIqM= +github.com/playwright-community/playwright-go v0.4702.0 h1:3CwNpk4RoA42tyhmlgPDMxYEYtMydaeEqMYiW0RNlSY= +github.com/playwright-community/playwright-go v0.4702.0/go.mod h1:bpArn5TqNzmP0jroCgw4poSOG9gSeQg490iLqWAaa7w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -1284,8 +1286,9 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1300,8 +1303,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= -golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1335,8 +1338,9 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1396,8 +1400,10 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1428,8 +1434,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1532,14 +1539,20 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc 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= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1550,8 +1563,11 @@ golang.org/x/text v0.3.5/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.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +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/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1632,8 +1648,9 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/danwakefield/fnmatch/LICENSE b/vendor/github.com/danwakefield/fnmatch/LICENSE deleted file mode 100644 index 0dc9851a3..000000000 --- a/vendor/github.com/danwakefield/fnmatch/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2016, Daniel Wakefield -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/danwakefield/fnmatch/README.md b/vendor/github.com/danwakefield/fnmatch/README.md deleted file mode 100644 index b8d715662..000000000 --- a/vendor/github.com/danwakefield/fnmatch/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# fnmatch -Updated clone of kballards golang fnmatch gist (https://gist.github.com/kballard/272720) - - diff --git a/vendor/github.com/danwakefield/fnmatch/fnmatch.go b/vendor/github.com/danwakefield/fnmatch/fnmatch.go deleted file mode 100644 index 07ac7b37c..000000000 --- a/vendor/github.com/danwakefield/fnmatch/fnmatch.go +++ /dev/null @@ -1,219 +0,0 @@ -// Provide string-matching based on fnmatch.3 -package fnmatch - -// There are a few issues that I believe to be bugs, but this implementation is -// based as closely as possible on BSD fnmatch. These bugs are present in the -// source of BSD fnmatch, and so are replicated here. The issues are as follows: -// -// * FNM_PERIOD is no longer observed after the first * in a pattern -// This only applies to matches done with FNM_PATHNAME as well -// * FNM_PERIOD doesn't apply to ranges. According to the documentation, -// a period must be matched explicitly, but a range will match it too - -import ( - "unicode" - "unicode/utf8" -) - -const ( - FNM_NOESCAPE = (1 << iota) - FNM_PATHNAME - FNM_PERIOD - - FNM_LEADING_DIR - FNM_CASEFOLD - - FNM_IGNORECASE = FNM_CASEFOLD - FNM_FILE_NAME = FNM_PATHNAME -) - -func unpackRune(str *string) rune { - rune, size := utf8.DecodeRuneInString(*str) - *str = (*str)[size:] - return rune -} - -// Matches the pattern against the string, with the given flags, -// and returns true if the match is successful. -// This function should match fnmatch.3 as closely as possible. -func Match(pattern, s string, flags int) bool { - // The implementation for this function was patterned after the BSD fnmatch.c - // source found at http://src.gnu-darwin.org/src/contrib/csup/fnmatch.c.html - noescape := (flags&FNM_NOESCAPE != 0) - pathname := (flags&FNM_PATHNAME != 0) - period := (flags&FNM_PERIOD != 0) - leadingdir := (flags&FNM_LEADING_DIR != 0) - casefold := (flags&FNM_CASEFOLD != 0) - // the following is some bookkeeping that the original fnmatch.c implementation did not do - // We are forced to do this because we're not keeping indexes into C strings but rather - // processing utf8-encoded strings. Use a custom unpacker to maintain our state for us - sAtStart := true - sLastAtStart := true - sLastSlash := false - sLastUnpacked := rune(0) - unpackS := func() rune { - sLastSlash = (sLastUnpacked == '/') - sLastUnpacked = unpackRune(&s) - sLastAtStart = sAtStart - sAtStart = false - return sLastUnpacked - } - for len(pattern) > 0 { - c := unpackRune(&pattern) - switch c { - case '?': - if len(s) == 0 { - return false - } - sc := unpackS() - if pathname && sc == '/' { - return false - } - if period && sc == '.' && (sLastAtStart || (pathname && sLastSlash)) { - return false - } - case '*': - // collapse multiple *'s - // don't use unpackRune here, the only char we care to detect is ASCII - for len(pattern) > 0 && pattern[0] == '*' { - pattern = pattern[1:] - } - if period && s[0] == '.' && (sAtStart || (pathname && sLastUnpacked == '/')) { - return false - } - // optimize for patterns with * at end or before / - if len(pattern) == 0 { - if pathname { - return leadingdir || (strchr(s, '/') == -1) - } else { - return true - } - return !(pathname && strchr(s, '/') >= 0) - } else if pathname && pattern[0] == '/' { - offset := strchr(s, '/') - if offset == -1 { - return false - } else { - // we already know our pattern and string have a /, skip past it - s = s[offset:] // use unpackS here to maintain our bookkeeping state - unpackS() - pattern = pattern[1:] // we know / is one byte long - break - } - } - // general case, recurse - for test := s; len(test) > 0; unpackRune(&test) { - // I believe the (flags &^ FNM_PERIOD) is a bug when FNM_PATHNAME is specified - // but this follows exactly from how fnmatch.c implements it - if Match(pattern, test, (flags &^ FNM_PERIOD)) { - return true - } else if pathname && test[0] == '/' { - break - } - } - return false - case '[': - if len(s) == 0 { - return false - } - if pathname && s[0] == '/' { - return false - } - sc := unpackS() - if !rangematch(&pattern, sc, flags) { - return false - } - case '\\': - if !noescape { - if len(pattern) > 0 { - c = unpackRune(&pattern) - } - } - fallthrough - default: - if len(s) == 0 { - return false - } - sc := unpackS() - switch { - case sc == c: - case casefold && unicode.ToLower(sc) == unicode.ToLower(c): - default: - return false - } - } - } - return len(s) == 0 || (leadingdir && s[0] == '/') -} - -func rangematch(pattern *string, test rune, flags int) bool { - if len(*pattern) == 0 { - return false - } - casefold := (flags&FNM_CASEFOLD != 0) - noescape := (flags&FNM_NOESCAPE != 0) - if casefold { - test = unicode.ToLower(test) - } - var negate, matched bool - if (*pattern)[0] == '^' || (*pattern)[0] == '!' { - negate = true - (*pattern) = (*pattern)[1:] - } - for !matched && len(*pattern) > 1 && (*pattern)[0] != ']' { - c := unpackRune(pattern) - if !noescape && c == '\\' { - if len(*pattern) > 1 { - c = unpackRune(pattern) - } else { - return false - } - } - if casefold { - c = unicode.ToLower(c) - } - if (*pattern)[0] == '-' && len(*pattern) > 1 && (*pattern)[1] != ']' { - unpackRune(pattern) // skip the - - c2 := unpackRune(pattern) - if !noescape && c2 == '\\' { - if len(*pattern) > 0 { - c2 = unpackRune(pattern) - } else { - return false - } - } - if casefold { - c2 = unicode.ToLower(c2) - } - // this really should be more intelligent, but it looks like - // fnmatch.c does simple int comparisons, therefore we will as well - if c <= test && test <= c2 { - matched = true - } - } else if c == test { - matched = true - } - } - // skip past the rest of the pattern - ok := false - for !ok && len(*pattern) > 0 { - c := unpackRune(pattern) - if c == '\\' && len(*pattern) > 0 { - unpackRune(pattern) - } else if c == ']' { - ok = true - } - } - return ok && matched != negate -} - -// define strchr because strings.Index() seems a bit overkill -// returns the index of c in s, or -1 if there is no match -func strchr(s string, c rune) int { - for i, sc := range s { - if sc == c { - return i - } - } - return -1 -} diff --git a/vendor/github.com/danwakefield/fnmatch/.gitignore b/vendor/github.com/deckarep/golang-set/v2/.gitignore similarity index 94% rename from vendor/github.com/danwakefield/fnmatch/.gitignore rename to vendor/github.com/deckarep/golang-set/v2/.gitignore index daf913b1b..4eb156d14 100644 --- a/vendor/github.com/danwakefield/fnmatch/.gitignore +++ b/vendor/github.com/deckarep/golang-set/v2/.gitignore @@ -20,5 +20,4 @@ _cgo_export.* _testmain.go *.exe -*.test -*.prof +.idea \ No newline at end of file diff --git a/vendor/github.com/deckarep/golang-set/v2/LICENSE b/vendor/github.com/deckarep/golang-set/v2/LICENSE new file mode 100644 index 000000000..efd4827e2 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/LICENSE @@ -0,0 +1,22 @@ +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) + +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. \ No newline at end of file diff --git a/vendor/github.com/deckarep/golang-set/v2/README.md b/vendor/github.com/deckarep/golang-set/v2/README.md new file mode 100644 index 000000000..921f0cec0 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/README.md @@ -0,0 +1,181 @@ +![example workflow](https://github.com/deckarep/golang-set/actions/workflows/ci.yml/badge.svg) +[![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set/v2)](https://goreportcard.com/report/github.com/deckarep/golang-set/v2) +[![GoDoc](https://godoc.org/github.com/deckarep/golang-set/v2?status.svg)](http://godoc.org/github.com/deckarep/golang-set/v2) + +# golang-set + +The missing `generic` set collection for the Go language. Until Go has sets built-in...use this. + +## Update 3/5/2023 +* Packaged version: `2.2.0` release includes a refactor to minimize pointer indirection, better method documentation standards and a few constructor convenience methods to increase ergonomics when appending items `Append` or creating a new set from an exist `Map`. +* supports `new generic` syntax +* Go `1.18.0` or higher +* Workflow tested on Go `1.20` + +![With Generics](new_improved.jpeg) + +Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set collection from Python. +You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository and carry-on and to the rest that find this useful please contribute in helping me make it better by contributing with suggestions or PRs. + +## Install + +Use `go get` to install this package. + +```shell +go get github.com/deckarep/golang-set/v2 +``` + +## Features + +* *NEW* [Generics](https://go.dev/doc/tutorial/generics) based implementation (requires [Go 1.18](https://go.dev/blog/go1.18beta1) or higher) +* One common *interface* to both implementations + * a **non threadsafe** implementation favoring *performance* + * a **threadsafe** implementation favoring *concurrent* use +* Feature complete set implementation modeled after [Python's set implementation](https://docs.python.org/3/library/stdtypes.html#set). +* Exhaustive unit-test and benchmark suite + +## Trusted by + +This package is trusted by many companies and thousands of open-source packages. Here are just a few sample users of this package. + +* Notable projects/companies using this package + * Ethereum + * Docker + * 1Password + * Hashicorp + +## Star History + +[![Star History Chart](https://api.star-history.com/svg?repos=deckarep/golang-set&type=Date)](https://star-history.com/#deckarep/golang-set&Date) + + +## Usage + +The code below demonstrates how a Set collection can better manage data and actually minimize boilerplate and needless loops in code. This package now fully supports *generic* syntax so you are now able to instantiate a collection for any [comparable](https://flaviocopes.com/golang-comparing-values/) type object. + +What is considered comparable in Go? +* `Booleans`, `integers`, `strings`, `floats` or basically primitive types. +* `Pointers` +* `Arrays` +* `Structs` if *all of their fields* are also comparable independently + +Using this library is as simple as creating either a threadsafe or non-threadsafe set and providing a `comparable` type for instantiation of the collection. + +```go +// Syntax example, doesn't compile. +mySet := mapset.NewSet[T]() // where T is some concrete comparable type. + +// Therefore this code creates an int set +mySet := mapset.NewSet[int]() + +// Or perhaps you want a string set +mySet := mapset.NewSet[string]() + +type myStruct struct { + name string + age uint8 +} + +// Alternatively a set of structs +mySet := mapset.NewSet[myStruct]() + +// Lastly a set that can hold anything using the any or empty interface keyword: interface{}. This is effectively removes type safety. +mySet := mapset.NewSet[any]() +``` + +## Comprehensive Example + +```go +package main + +import ( + "fmt" + mapset "github.com/deckarep/golang-set/v2" +) + +func main() { + // Create a string-based set of required classes. + required := mapset.NewSet[string]() + required.Add("cooking") + required.Add("english") + required.Add("math") + required.Add("biology") + + // Create a string-based set of science classes. + sciences := mapset.NewSet[string]() + sciences.Add("biology") + sciences.Add("chemistry") + + // Create a string-based set of electives. + electives := mapset.NewSet[string]() + electives.Add("welding") + electives.Add("music") + electives.Add("automotive") + + // Create a string-based set of bonus programming classes. + bonus := mapset.NewSet[string]() + bonus.Add("beginner go") + bonus.Add("python for dummies") +} +``` + +Create a set of all unique classes. +Sets will *automatically* deduplicate the same data. + +```go + all := required + .Union(sciences) + .Union(electives) + .Union(bonus) + + fmt.Println(all) +``` + +Output: +```sh +Set{cooking, english, math, chemistry, welding, biology, music, automotive, beginner go, python for dummies} +``` + +Is cooking considered a science class? +```go +result := sciences.Contains("cooking") +fmt.Println(result) +``` + +Output: +```false +false +``` + +Show me all classes that are not science classes, since I don't enjoy science. +```go +notScience := all.Difference(sciences) +fmt.Println(notScience) +``` + +```sh +Set{ music, automotive, beginner go, python for dummies, cooking, english, math, welding } +``` + +Which science classes are also required classes? +```go +reqScience := sciences.Intersect(required) +``` + +Output: +```sh +Set{biology} +``` + +How many bonus classes do you offer? +```go +fmt.Println(bonus.Cardinality()) +``` +Output: +```sh +2 +``` + +Thanks for visiting! + +-deckarep diff --git a/vendor/github.com/deckarep/golang-set/v2/iterator.go b/vendor/github.com/deckarep/golang-set/v2/iterator.go new file mode 100644 index 000000000..fc14e7056 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/iterator.go @@ -0,0 +1,58 @@ +/* +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) + +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. +*/ + +package mapset + +// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's +// elements. +type Iterator[T comparable] struct { + C <-chan T + stop chan struct{} +} + +// Stop stops the Iterator, no further elements will be received on C, C will be closed. +func (i *Iterator[T]) Stop() { + // Allows for Stop() to be called multiple times + // (close() panics when called on already closed channel) + defer func() { + recover() + }() + + close(i.stop) + + // Exhaust any remaining elements. + for range i.C { + } +} + +// newIterator returns a new Iterator instance together with its item and stop channels. +func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) { + itemChan := make(chan T) + stopChan := make(chan struct{}) + return &Iterator[T]{ + C: itemChan, + stop: stopChan, + }, itemChan, stopChan +} diff --git a/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg b/vendor/github.com/deckarep/golang-set/v2/new_improved.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..429752a07a94b837434515275aa7645714879341 GIT binary patch literal 120935 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/deckarep/golang-set/v2/set.go b/vendor/github.com/deckarep/golang-set/v2/set.go new file mode 100644 index 000000000..292089dcf --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/set.go @@ -0,0 +1,255 @@ +/* +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) + +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. +*/ + +// Package mapset implements a simple and set collection. +// Items stored within it are unordered and unique. It supports +// typical set operations: membership testing, intersection, union, +// difference, symmetric difference and cloning. +// +// Package mapset provides two implementations of the Set +// interface. The default implementation is safe for concurrent +// access, but a non-thread-safe implementation is also provided for +// programs that can benefit from the slight speed improvement and +// that can enforce mutual exclusion through other means. +package mapset + +// Set is the primary interface provided by the mapset package. It +// represents an unordered set of data and a large number of +// operations that can be applied to that set. +type Set[T comparable] interface { + // Add adds an element to the set. Returns whether + // the item was added. + Add(val T) bool + + // Append multiple elements to the set. Returns + // the number of elements added. + Append(val ...T) int + + // Cardinality returns the number of elements in the set. + Cardinality() int + + // Clear removes all elements from the set, leaving + // the empty set. + Clear() + + // Clone returns a clone of the set using the same + // implementation, duplicating all keys. + Clone() Set[T] + + // Contains returns whether the given items + // are all in the set. + Contains(val ...T) bool + + // ContainsOne returns whether the given item + // is in the set. + // + // Contains may cause the argument to escape to the heap. + // See: https://github.com/deckarep/golang-set/issues/118 + ContainsOne(val T) bool + + // ContainsAny returns whether at least one of the + // given items are in the set. + ContainsAny(val ...T) bool + + // Difference returns the difference between this set + // and other. The returned set will contain + // all elements of this set that are not also + // elements of other. + // + // Note that the argument to Difference + // must be of the same type as the receiver + // of the method. Otherwise, Difference will + // panic. + Difference(other Set[T]) Set[T] + + // Equal determines if two sets are equal to each + // other. If they have the same cardinality + // and contain the same elements, they are + // considered equal. The order in which + // the elements were added is irrelevant. + // + // Note that the argument to Equal must be + // of the same type as the receiver of the + // method. Otherwise, Equal will panic. + Equal(other Set[T]) bool + + // Intersect returns a new set containing only the elements + // that exist only in both sets. + // + // Note that the argument to Intersect + // must be of the same type as the receiver + // of the method. Otherwise, Intersect will + // panic. + Intersect(other Set[T]) Set[T] + + // IsEmpty determines if there are elements in the set. + IsEmpty() bool + + // IsProperSubset determines if every element in this set is in + // the other set but the two sets are not equal. + // + // Note that the argument to IsProperSubset + // must be of the same type as the receiver + // of the method. Otherwise, IsProperSubset + // will panic. + IsProperSubset(other Set[T]) bool + + // IsProperSuperset determines if every element in the other set + // is in this set but the two sets are not + // equal. + // + // Note that the argument to IsSuperset + // must be of the same type as the receiver + // of the method. Otherwise, IsSuperset will + // panic. + IsProperSuperset(other Set[T]) bool + + // IsSubset determines if every element in this set is in + // the other set. + // + // Note that the argument to IsSubset + // must be of the same type as the receiver + // of the method. Otherwise, IsSubset will + // panic. + IsSubset(other Set[T]) bool + + // IsSuperset determines if every element in the other set + // is in this set. + // + // Note that the argument to IsSuperset + // must be of the same type as the receiver + // of the method. Otherwise, IsSuperset will + // panic. + IsSuperset(other Set[T]) bool + + // Each iterates over elements and executes the passed func against each element. + // If passed func returns true, stop iteration at the time. + Each(func(T) bool) + + // Iter returns a channel of elements that you can + // range over. + Iter() <-chan T + + // Iterator returns an Iterator object that you can + // use to range over the set. + Iterator() *Iterator[T] + + // Remove removes a single element from the set. + Remove(i T) + + // RemoveAll removes multiple elements from the set. + RemoveAll(i ...T) + + // String provides a convenient string representation + // of the current state of the set. + String() string + + // SymmetricDifference returns a new set with all elements which are + // in either this set or the other set but not in both. + // + // Note that the argument to SymmetricDifference + // must be of the same type as the receiver + // of the method. Otherwise, SymmetricDifference + // will panic. + SymmetricDifference(other Set[T]) Set[T] + + // Union returns a new set with all elements in both sets. + // + // Note that the argument to Union must be of the + // same type as the receiver of the method. + // Otherwise, Union will panic. + Union(other Set[T]) Set[T] + + // Pop removes and returns an arbitrary item from the set. + Pop() (T, bool) + + // ToSlice returns the members of the set as a slice. + ToSlice() []T + + // MarshalJSON will marshal the set into a JSON-based representation. + MarshalJSON() ([]byte, error) + + // UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure. + // For this to work, set subtypes must implemented the Marshal/Unmarshal interface. + UnmarshalJSON(b []byte) error +} + +// NewSet creates and returns a new set with the given elements. +// Operations on the resulting set are thread-safe. +func NewSet[T comparable](vals ...T) Set[T] { + s := newThreadSafeSetWithSize[T](len(vals)) + for _, item := range vals { + s.Add(item) + } + return s +} + +// NewSetWithSize creates and returns a reference to an empty set with a specified +// capacity. Operations on the resulting set are thread-safe. +func NewSetWithSize[T comparable](cardinality int) Set[T] { + s := newThreadSafeSetWithSize[T](cardinality) + return s +} + +// NewThreadUnsafeSet creates and returns a new set with the given elements. +// Operations on the resulting set are not thread-safe. +func NewThreadUnsafeSet[T comparable](vals ...T) Set[T] { + s := newThreadUnsafeSetWithSize[T](len(vals)) + for _, item := range vals { + s.Add(item) + } + return s +} + +// NewThreadUnsafeSetWithSize creates and returns a reference to an empty set with +// a specified capacity. Operations on the resulting set are not thread-safe. +func NewThreadUnsafeSetWithSize[T comparable](cardinality int) Set[T] { + s := newThreadUnsafeSetWithSize[T](cardinality) + return s +} + +// NewSetFromMapKeys creates and returns a new set with the given keys of the map. +// Operations on the resulting set are thread-safe. +func NewSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] { + s := NewSetWithSize[T](len(val)) + + for k := range val { + s.Add(k) + } + + return s +} + +// NewThreadUnsafeSetFromMapKeys creates and returns a new set with the given keys of the map. +// Operations on the resulting set are not thread-safe. +func NewThreadUnsafeSetFromMapKeys[T comparable, V any](val map[T]V) Set[T] { + s := NewThreadUnsafeSetWithSize[T](len(val)) + + for k := range val { + s.Add(k) + } + + return s +} diff --git a/vendor/github.com/deckarep/golang-set/v2/sorted.go b/vendor/github.com/deckarep/golang-set/v2/sorted.go new file mode 100644 index 000000000..8ee2e7076 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/sorted.go @@ -0,0 +1,42 @@ +//go:build go1.21 +// +build go1.21 + +/* +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2023 Ralph Caraveo (deckarep@gmail.com) + +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. +*/ + +package mapset + +import ( + "cmp" + "slices" +) + +// Sorted returns a sorted slice of a set of any ordered type in ascending order. +// When sorting floating-point numbers, NaNs are ordered before other values. +func Sorted[E cmp.Ordered](set Set[E]) []E { + s := set.ToSlice() + slices.Sort(s) + return s +} diff --git a/vendor/github.com/deckarep/golang-set/v2/threadsafe.go b/vendor/github.com/deckarep/golang-set/v2/threadsafe.go new file mode 100644 index 000000000..ad7a834b5 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/threadsafe.go @@ -0,0 +1,299 @@ +/* +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) + +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. +*/ + +package mapset + +import "sync" + +type threadSafeSet[T comparable] struct { + sync.RWMutex + uss threadUnsafeSet[T] +} + +func newThreadSafeSet[T comparable]() *threadSafeSet[T] { + return &threadSafeSet[T]{ + uss: newThreadUnsafeSet[T](), + } +} + +func newThreadSafeSetWithSize[T comparable](cardinality int) *threadSafeSet[T] { + return &threadSafeSet[T]{ + uss: newThreadUnsafeSetWithSize[T](cardinality), + } +} + +func (t *threadSafeSet[T]) Add(v T) bool { + t.Lock() + ret := t.uss.Add(v) + t.Unlock() + return ret +} + +func (t *threadSafeSet[T]) Append(v ...T) int { + t.Lock() + ret := t.uss.Append(v...) + t.Unlock() + return ret +} + +func (t *threadSafeSet[T]) Contains(v ...T) bool { + t.RLock() + ret := t.uss.Contains(v...) + t.RUnlock() + + return ret +} + +func (t *threadSafeSet[T]) ContainsOne(v T) bool { + t.RLock() + ret := t.uss.ContainsOne(v) + t.RUnlock() + + return ret +} + +func (t *threadSafeSet[T]) ContainsAny(v ...T) bool { + t.RLock() + ret := t.uss.ContainsAny(v...) + t.RUnlock() + + return ret +} + +func (t *threadSafeSet[T]) IsEmpty() bool { + return t.Cardinality() == 0 +} + +func (t *threadSafeSet[T]) IsSubset(other Set[T]) bool { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + ret := t.uss.IsSubset(o.uss) + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) IsProperSubset(other Set[T]) bool { + o := other.(*threadSafeSet[T]) + + t.RLock() + defer t.RUnlock() + o.RLock() + defer o.RUnlock() + + return t.uss.IsProperSubset(o.uss) +} + +func (t *threadSafeSet[T]) IsSuperset(other Set[T]) bool { + return other.IsSubset(t) +} + +func (t *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool { + return other.IsProperSubset(t) +} + +func (t *threadSafeSet[T]) Union(other Set[T]) Set[T] { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + unsafeUnion := t.uss.Union(o.uss).(threadUnsafeSet[T]) + ret := &threadSafeSet[T]{uss: unsafeUnion} + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) Intersect(other Set[T]) Set[T] { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + unsafeIntersection := t.uss.Intersect(o.uss).(threadUnsafeSet[T]) + ret := &threadSafeSet[T]{uss: unsafeIntersection} + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) Difference(other Set[T]) Set[T] { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + unsafeDifference := t.uss.Difference(o.uss).(threadUnsafeSet[T]) + ret := &threadSafeSet[T]{uss: unsafeDifference} + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + unsafeDifference := t.uss.SymmetricDifference(o.uss).(threadUnsafeSet[T]) + ret := &threadSafeSet[T]{uss: unsafeDifference} + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) Clear() { + t.Lock() + t.uss.Clear() + t.Unlock() +} + +func (t *threadSafeSet[T]) Remove(v T) { + t.Lock() + delete(t.uss, v) + t.Unlock() +} + +func (t *threadSafeSet[T]) RemoveAll(i ...T) { + t.Lock() + t.uss.RemoveAll(i...) + t.Unlock() +} + +func (t *threadSafeSet[T]) Cardinality() int { + t.RLock() + defer t.RUnlock() + return len(t.uss) +} + +func (t *threadSafeSet[T]) Each(cb func(T) bool) { + t.RLock() + for elem := range t.uss { + if cb(elem) { + break + } + } + t.RUnlock() +} + +func (t *threadSafeSet[T]) Iter() <-chan T { + ch := make(chan T) + go func() { + t.RLock() + + for elem := range t.uss { + ch <- elem + } + close(ch) + t.RUnlock() + }() + + return ch +} + +func (t *threadSafeSet[T]) Iterator() *Iterator[T] { + iterator, ch, stopCh := newIterator[T]() + + go func() { + t.RLock() + L: + for elem := range t.uss { + select { + case <-stopCh: + break L + case ch <- elem: + } + } + close(ch) + t.RUnlock() + }() + + return iterator +} + +func (t *threadSafeSet[T]) Equal(other Set[T]) bool { + o := other.(*threadSafeSet[T]) + + t.RLock() + o.RLock() + + ret := t.uss.Equal(o.uss) + t.RUnlock() + o.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) Clone() Set[T] { + t.RLock() + + unsafeClone := t.uss.Clone().(threadUnsafeSet[T]) + ret := &threadSafeSet[T]{uss: unsafeClone} + t.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) String() string { + t.RLock() + ret := t.uss.String() + t.RUnlock() + return ret +} + +func (t *threadSafeSet[T]) Pop() (T, bool) { + t.Lock() + defer t.Unlock() + return t.uss.Pop() +} + +func (t *threadSafeSet[T]) ToSlice() []T { + keys := make([]T, 0, t.Cardinality()) + t.RLock() + for elem := range t.uss { + keys = append(keys, elem) + } + t.RUnlock() + return keys +} + +func (t *threadSafeSet[T]) MarshalJSON() ([]byte, error) { + t.RLock() + b, err := t.uss.MarshalJSON() + t.RUnlock() + + return b, err +} + +func (t *threadSafeSet[T]) UnmarshalJSON(p []byte) error { + t.RLock() + err := t.uss.UnmarshalJSON(p) + t.RUnlock() + + return err +} diff --git a/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go b/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go new file mode 100644 index 000000000..8b17b0176 --- /dev/null +++ b/vendor/github.com/deckarep/golang-set/v2/threadunsafe.go @@ -0,0 +1,330 @@ +/* +Open Source Initiative OSI - The MIT License (MIT):Licensing + +The MIT License (MIT) +Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com) + +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. +*/ + +package mapset + +import ( + "encoding/json" + "fmt" + "strings" +) + +type threadUnsafeSet[T comparable] map[T]struct{} + +// Assert concrete type:threadUnsafeSet adheres to Set interface. +var _ Set[string] = (threadUnsafeSet[string])(nil) + +func newThreadUnsafeSet[T comparable]() threadUnsafeSet[T] { + return make(threadUnsafeSet[T]) +} + +func newThreadUnsafeSetWithSize[T comparable](cardinality int) threadUnsafeSet[T] { + return make(threadUnsafeSet[T], cardinality) +} + +func (s threadUnsafeSet[T]) Add(v T) bool { + prevLen := len(s) + s[v] = struct{}{} + return prevLen != len(s) +} + +func (s threadUnsafeSet[T]) Append(v ...T) int { + prevLen := len(s) + for _, val := range v { + (s)[val] = struct{}{} + } + return len(s) - prevLen +} + +// private version of Add which doesn't return a value +func (s threadUnsafeSet[T]) add(v T) { + s[v] = struct{}{} +} + +func (s threadUnsafeSet[T]) Cardinality() int { + return len(s) +} + +func (s threadUnsafeSet[T]) Clear() { + // Constructions like this are optimised by compiler, and replaced by + // mapclear() function, defined in + // https://github.com/golang/go/blob/29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4/src/runtime/map.go#L993) + for key := range s { + delete(s, key) + } +} + +func (s threadUnsafeSet[T]) Clone() Set[T] { + clonedSet := newThreadUnsafeSetWithSize[T](s.Cardinality()) + for elem := range s { + clonedSet.add(elem) + } + return clonedSet +} + +func (s threadUnsafeSet[T]) Contains(v ...T) bool { + for _, val := range v { + if _, ok := s[val]; !ok { + return false + } + } + return true +} + +func (s threadUnsafeSet[T]) ContainsOne(v T) bool { + _, ok := s[v] + return ok +} + +func (s threadUnsafeSet[T]) ContainsAny(v ...T) bool { + for _, val := range v { + if _, ok := s[val]; ok { + return true + } + } + return false +} + +// private version of Contains for a single element v +func (s threadUnsafeSet[T]) contains(v T) (ok bool) { + _, ok = s[v] + return ok +} + +func (s threadUnsafeSet[T]) Difference(other Set[T]) Set[T] { + o := other.(threadUnsafeSet[T]) + + diff := newThreadUnsafeSet[T]() + for elem := range s { + if !o.contains(elem) { + diff.add(elem) + } + } + return diff +} + +func (s threadUnsafeSet[T]) Each(cb func(T) bool) { + for elem := range s { + if cb(elem) { + break + } + } +} + +func (s threadUnsafeSet[T]) Equal(other Set[T]) bool { + o := other.(threadUnsafeSet[T]) + + if s.Cardinality() != other.Cardinality() { + return false + } + for elem := range s { + if !o.contains(elem) { + return false + } + } + return true +} + +func (s threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] { + o := other.(threadUnsafeSet[T]) + + intersection := newThreadUnsafeSet[T]() + // loop over smaller set + if s.Cardinality() < other.Cardinality() { + for elem := range s { + if o.contains(elem) { + intersection.add(elem) + } + } + } else { + for elem := range o { + if s.contains(elem) { + intersection.add(elem) + } + } + } + return intersection +} + +func (s threadUnsafeSet[T]) IsEmpty() bool { + return s.Cardinality() == 0 +} + +func (s threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool { + return s.Cardinality() < other.Cardinality() && s.IsSubset(other) +} + +func (s threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool { + return s.Cardinality() > other.Cardinality() && s.IsSuperset(other) +} + +func (s threadUnsafeSet[T]) IsSubset(other Set[T]) bool { + o := other.(threadUnsafeSet[T]) + if s.Cardinality() > other.Cardinality() { + return false + } + for elem := range s { + if !o.contains(elem) { + return false + } + } + return true +} + +func (s threadUnsafeSet[T]) IsSuperset(other Set[T]) bool { + return other.IsSubset(s) +} + +func (s threadUnsafeSet[T]) Iter() <-chan T { + ch := make(chan T) + go func() { + for elem := range s { + ch <- elem + } + close(ch) + }() + + return ch +} + +func (s threadUnsafeSet[T]) Iterator() *Iterator[T] { + iterator, ch, stopCh := newIterator[T]() + + go func() { + L: + for elem := range s { + select { + case <-stopCh: + break L + case ch <- elem: + } + } + close(ch) + }() + + return iterator +} + +// Pop returns a popped item in case set is not empty, or nil-value of T +// if set is already empty +func (s threadUnsafeSet[T]) Pop() (v T, ok bool) { + for item := range s { + delete(s, item) + return item, true + } + return v, false +} + +func (s threadUnsafeSet[T]) Remove(v T) { + delete(s, v) +} + +func (s threadUnsafeSet[T]) RemoveAll(i ...T) { + for _, elem := range i { + delete(s, elem) + } +} + +func (s threadUnsafeSet[T]) String() string { + items := make([]string, 0, len(s)) + + for elem := range s { + items = append(items, fmt.Sprintf("%v", elem)) + } + return fmt.Sprintf("Set{%s}", strings.Join(items, ", ")) +} + +func (s threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] { + o := other.(threadUnsafeSet[T]) + + sd := newThreadUnsafeSet[T]() + for elem := range s { + if !o.contains(elem) { + sd.add(elem) + } + } + for elem := range o { + if !s.contains(elem) { + sd.add(elem) + } + } + return sd +} + +func (s threadUnsafeSet[T]) ToSlice() []T { + keys := make([]T, 0, s.Cardinality()) + for elem := range s { + keys = append(keys, elem) + } + + return keys +} + +func (s threadUnsafeSet[T]) Union(other Set[T]) Set[T] { + o := other.(threadUnsafeSet[T]) + + n := s.Cardinality() + if o.Cardinality() > n { + n = o.Cardinality() + } + unionedSet := make(threadUnsafeSet[T], n) + + for elem := range s { + unionedSet.add(elem) + } + for elem := range o { + unionedSet.add(elem) + } + return unionedSet +} + +// MarshalJSON creates a JSON array from the set, it marshals all elements +func (s threadUnsafeSet[T]) MarshalJSON() ([]byte, error) { + items := make([]string, 0, s.Cardinality()) + + for elem := range s { + b, err := json.Marshal(elem) + if err != nil { + return nil, err + } + + items = append(items, string(b)) + } + + return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil +} + +// UnmarshalJSON recreates a set from a JSON array, it only decodes +// primitive types. Numbers are decoded as json.Number. +func (s threadUnsafeSet[T]) UnmarshalJSON(b []byte) error { + var i []T + err := json.Unmarshal(b, &i) + if err != nil { + return err + } + s.Append(i...) + + return nil +} diff --git a/vendor/github.com/go-jose/go-jose/v3/json/decode.go b/vendor/github.com/go-jose/go-jose/v3/json/decode.go index 4dbc4146c..50634dd84 100644 --- a/vendor/github.com/go-jose/go-jose/v3/json/decode.go +++ b/vendor/github.com/go-jose/go-jose/v3/json/decode.go @@ -75,14 +75,13 @@ import ( // // The JSON null value unmarshals into an interface, map, pointer, or slice // by setting that Go value to nil. Because null is often used in JSON to mean -// ``not present,'' unmarshaling a JSON null into any other Go type has no effect +// β€œnot present,” unmarshaling a JSON null into any other Go type has no effect // on the value and produces no error. // // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement // character U+FFFD. -// func Unmarshal(data []byte, v interface{}) error { // Check for well-formedness. // Avoids filling out half a data structure diff --git a/vendor/github.com/go-jose/go-jose/v3/json/encode.go b/vendor/github.com/go-jose/go-jose/v3/json/encode.go index ea0a13619..98de68ce1 100644 --- a/vendor/github.com/go-jose/go-jose/v3/json/encode.go +++ b/vendor/github.com/go-jose/go-jose/v3/json/encode.go @@ -58,6 +58,7 @@ import ( // becomes a member of the object unless // - the field's tag is "-", or // - the field is empty and its tag specifies the "omitempty" option. +// // The empty values are false, 0, any // nil pointer or interface value, and any array, slice, map, or string of // length zero. The object's default key string is the struct field name @@ -65,28 +66,28 @@ import ( // the struct field's tag value is the key name, followed by an optional comma // and options. Examples: // -// // Field is ignored by this package. -// Field int `json:"-"` +// // Field is ignored by this package. +// Field int `json:"-"` // -// // Field appears in JSON as key "myName". -// Field int `json:"myName"` +// // Field appears in JSON as key "myName". +// Field int `json:"myName"` // -// // Field appears in JSON as key "myName" and -// // the field is omitted from the object if its value is empty, -// // as defined above. -// Field int `json:"myName,omitempty"` +// // Field appears in JSON as key "myName" and +// // the field is omitted from the object if its value is empty, +// // as defined above. +// Field int `json:"myName,omitempty"` // -// // Field appears in JSON as key "Field" (the default), but -// // the field is skipped if empty. -// // Note the leading comma. -// Field int `json:",omitempty"` +// // Field appears in JSON as key "Field" (the default), but +// // the field is skipped if empty. +// // Note the leading comma. +// Field int `json:",omitempty"` // // The "string" option signals that a field is stored as JSON inside a // JSON-encoded string. It applies only to fields of string, floating point, // integer, or boolean types. This extra level of encoding is sometimes used // when communicating with JavaScript programs: // -// Int64String int64 `json:",string"` +// Int64String int64 `json:",string"` // // The key name will be used if it's a non-empty string consisting of // only Unicode letters, digits, dollar signs, percent signs, hyphens, @@ -133,7 +134,6 @@ import ( // JSON cannot represent cyclic data structures and Marshal does not // handle them. Passing cyclic structures to Marshal will result in // an infinite recursion. -// func Marshal(v interface{}) ([]byte, error) { e := &encodeState{} err := e.marshal(v) diff --git a/vendor/github.com/go-jose/go-jose/v3/json/stream.go b/vendor/github.com/go-jose/go-jose/v3/json/stream.go index 9b2b926b0..f03b171e6 100644 --- a/vendor/github.com/go-jose/go-jose/v3/json/stream.go +++ b/vendor/github.com/go-jose/go-jose/v3/json/stream.go @@ -240,7 +240,6 @@ var _ Unmarshaler = (*RawMessage)(nil) // Number, for JSON numbers // string, for JSON string literals // nil, for JSON null -// type Token interface{} const ( diff --git a/vendor/github.com/playwright-community/playwright-go/.gitignore b/vendor/github.com/playwright-community/playwright-go/.gitignore index fa6b0aa17..83e23552e 100644 --- a/vendor/github.com/playwright-community/playwright-go/.gitignore +++ b/vendor/github.com/playwright-community/playwright-go/.gitignore @@ -29,4 +29,6 @@ covprofile api.json _site/ -.jekyll-cache/ \ No newline at end of file +.jekyll-cache/ + +.vscode/settings.json \ No newline at end of file diff --git a/vendor/github.com/playwright-community/playwright-go/.golangci.yaml b/vendor/github.com/playwright-community/playwright-go/.golangci.yaml new file mode 100644 index 000000000..1557a3f3a --- /dev/null +++ b/vendor/github.com/playwright-community/playwright-go/.golangci.yaml @@ -0,0 +1,6 @@ +--- +linters: + enable-all: false + disable-all: false + enable: + - gofumpt \ No newline at end of file diff --git a/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md index 7b00cd505..3b11995ec 100644 --- a/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md +++ b/vendor/github.com/playwright-community/playwright-go/CONTRIBUTING.md @@ -1,5 +1,8 @@ # Contributing +## Code style +The Go code is linted with [golangci-lint](https://golangci-lint.run/) and formatted with [gofumpt](https://github.com/mvdan/gofumpt). Please configure your editor to run the tools while developing and make sure to run the tools before committing any code. + ## Tests ### Test coverage diff --git a/vendor/github.com/playwright-community/playwright-go/Dockerfile.example b/vendor/github.com/playwright-community/playwright-go/Dockerfile.example new file mode 100644 index 000000000..6597cc5c5 --- /dev/null +++ b/vendor/github.com/playwright-community/playwright-go/Dockerfile.example @@ -0,0 +1,25 @@ +# Stage 1: Modules caching +FROM golang:1.21 as modules +COPY go.mod go.sum /modules/ +WORKDIR /modules +RUN go mod download + +# Stage 2: Build +FROM golang:1.21 as builder +COPY --from=modules /go/pkg /go/pkg +COPY . /workdir +WORKDIR /workdir +# Install playwright cli with right version for later use +RUN PWGO_VER=$(grep -oE "playwright-go v\S+" /workdir/go.mod | sed 's/playwright-go //g') \ + && go install github.com/playwright-community/playwright-go/cmd/playwright@${PWGO_VER} +# Build your app +RUN GOOS=linux GOARCH=amd64 go build -o /bin/myapp + +# Stage 3: Final +FROM ubuntu:jammy +COPY --from=builder /go/bin/playwright /bin/myapp / +RUN apt-get update && apt-get install -y ca-certificates tzdata \ + # Install dependencies and all browsers (or specify one) + && /playwright install --with-deps \ + && rm -rf /var/lib/apt/lists/* +CMD ["/myapp"] \ No newline at end of file diff --git a/vendor/github.com/playwright-community/playwright-go/README.md b/vendor/github.com/playwright-community/playwright-go/README.md index 09dc5c011..02ac77d2c 100644 --- a/vendor/github.com/playwright-community/playwright-go/README.md +++ b/vendor/github.com/playwright-community/playwright-go/README.md @@ -5,7 +5,7 @@ [![PkgGoDev](https://pkg.go.dev/badge/github.com/playwright-community/playwright-go)](https://pkg.go.dev/github.com/playwright-community/playwright-go) [![License](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT) [![Go Report Card](https://goreportcard.com/badge/github.com/playwright-community/playwright-go)](https://goreportcard.com/report/github.com/playwright-community/playwright-go) ![Build Status](https://github.com/playwright-community/playwright-go/workflows/Go/badge.svg) -[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) [![Chromium version](https://img.shields.io/badge/chromium-119.0.6045.9-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-118.0.1-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) +[![Join Slack](https://img.shields.io/badge/join-slack-infomational)](https://aka.ms/playwright-slack) [![Coverage Status](https://coveralls.io/repos/github/playwright-community/playwright-go/badge.svg?branch=main)](https://coveralls.io/github/playwright-community/playwright-go?branch=main) [![Chromium version](https://img.shields.io/badge/chromium-129.0.6668.29-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-130.0-blue.svg?logo=mozilla-firefox)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [API reference](https://playwright.dev/docs/api/class-playwright) | [Example recipes](https://github.com/playwright-community/playwright-go/tree/main/examples) @@ -13,9 +13,9 @@ Playwright is a Go library to automate [Chromium](https://www.chromium.org/Home) | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 119.0.6045.9 | βœ… | βœ… | βœ… | -| WebKit 17.4 | βœ… | βœ… | βœ… | -| Firefox 118.0.1 | βœ… | βœ… | βœ… | +| Chromium 129.0.6668.29 | βœ… | βœ… | βœ… | +| WebKit 18.0 | βœ… | βœ… | βœ… | +| Firefox 130.0 | βœ… | βœ… | βœ… | Headless execution is supported for all the browsers on all platforms. @@ -103,8 +103,12 @@ func main() { } ``` +## Docker +Refer to the [Dockerfile.example](./Dockerfile.example) to build your own docker image. + ## More examples +* Refer to [helper_test.go](./tests/helper_test.go) for End-To-End testing * [Downloading files](./examples/download/main.go) * [End-To-End testing a website](./examples/end-to-end-testing/main.go) * [Executing JavaScript in the browser](./examples/javascript/main.go) diff --git a/vendor/github.com/playwright-community/playwright-go/artifact.go b/vendor/github.com/playwright-community/playwright-go/artifact.go index 35e910d83..c76b8927d 100644 --- a/vendor/github.com/playwright-community/playwright-go/artifact.go +++ b/vendor/github.com/playwright-community/playwright-go/artifact.go @@ -18,9 +18,6 @@ func (a *artifactImpl) PathAfterFinished() (string, error) { return "", errors.New("Path is not available when connecting remotely. Use SaveAs() to save a local copy") } path, err := a.channel.Send("pathAfterFinished") - if path == nil { - return "", err - } return path.(string), err } @@ -40,11 +37,11 @@ func (a *artifactImpl) SaveAs(path string) error { } func (a *artifactImpl) Failure() error { - failure, err := a.channel.Send("failure") - if failure == nil { + reason, err := a.channel.Send("failure") + if reason == nil { return err } - return fmt.Errorf("%v", failure) + return fmt.Errorf("%w: %v", ErrPlaywright, reason) } func (a *artifactImpl) Delete() error { @@ -62,10 +59,7 @@ func (a *artifactImpl) ReadIntoBuffer() ([]byte, error) { if err != nil { return nil, err } - stream := fromNullableChannel(streamChannel) - if stream == nil { - return nil, nil - } + stream := fromChannel(streamChannel) return stream.(*streamImpl).ReadAll() } diff --git a/vendor/github.com/playwright-community/playwright-go/assertions.go b/vendor/github.com/playwright-community/playwright-go/assertions.go index 43f35b4a9..c7e97f5f7 100644 --- a/vendor/github.com/playwright-community/playwright-go/assertions.go +++ b/vendor/github.com/playwright-community/playwright-go/assertions.go @@ -1,6 +1,7 @@ package playwright import ( + "errors" "fmt" "reflect" "regexp" @@ -103,7 +104,7 @@ func toExpectedTextValues( matchSubstring bool, normalizeWhiteSpace bool, ignoreCase *bool, -) []expectedTextValue { +) ([]expectedTextValue, error) { var out []expectedTextValue for _, item := range items { switch item := item.(type) { @@ -123,9 +124,11 @@ func toExpectedTextValues( NormalizeWhiteSpace: Bool(normalizeWhiteSpace), IgnoreCase: ignoreCase, }) + default: + return nil, errors.New("value must be a string or regexp") } } - return out + return out, nil } func convertToInterfaceList(v interface{}) []interface{} { diff --git a/vendor/github.com/playwright-community/playwright-go/binding_call.go b/vendor/github.com/playwright-community/playwright-go/binding_call.go index 80a13153e..a018557bf 100644 --- a/vendor/github.com/playwright-community/playwright-go/binding_call.go +++ b/vendor/github.com/playwright-community/playwright-go/binding_call.go @@ -1,7 +1,10 @@ package playwright import ( - "log" + "fmt" + "strings" + + "github.com/go-stack/stack" ) type BindingCall interface { @@ -31,7 +34,7 @@ func (b *bindingCallImpl) Call(f BindingCallFunction) { if _, err := b.channel.Send("reject", map[string]interface{}{ "error": serializeError(r.(error)), }); err != nil { - log.Printf("could not reject BindingCall: %v", err) + logger.Printf("could not reject BindingCall: %v\n", err) } } }() @@ -57,7 +60,23 @@ func (b *bindingCallImpl) Call(f BindingCallFunction) { "result": serializeArgument(result), }) if err != nil { - log.Printf("could not resolve BindingCall: %v", err) + logger.Printf("could not resolve BindingCall: %v\n", err) + } +} + +func serializeError(err error) map[string]interface{} { + st := stack.Trace().TrimRuntime() + if len(st) == 0 { // https://github.com/go-stack/stack/issues/27 + st = stack.Trace() + } + return map[string]interface{}{ + "error": &Error{ + Name: "Playwright for Go Error", + Message: err.Error(), + Stack: strings.ReplaceAll(strings.TrimFunc(fmt.Sprintf("%+v", st), func(r rune) bool { + return r == '[' || r == ']' + }), " ", "\n"), + }, } } diff --git a/vendor/github.com/playwright-community/playwright-go/browser.go b/vendor/github.com/playwright-community/playwright-go/browser.go index 6f14ca2d7..c87540abb 100644 --- a/vendor/github.com/playwright-community/playwright-go/browser.go +++ b/vendor/github.com/playwright-community/playwright-go/browser.go @@ -1,7 +1,9 @@ package playwright import ( + "encoding/base64" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -10,11 +12,11 @@ import ( type browserImpl struct { channelOwner isConnected bool - isClosedOrClosing bool shouldCloseConnectionOnClose bool contexts []BrowserContext browserType BrowserType chromiumTracingPath *string + closeReason *string } func (b *browserImpl) BrowserType() BrowserType { @@ -45,6 +47,14 @@ func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserCo overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders) options[0].ExtraHttpHeaders = nil } + if option.ClientCertificates != nil { + certs, err := transformClientCertificate(option.ClientCertificates) + if err != nil { + return nil, err + } + overrides["clientCertificates"] = certs + options[0].ClientCertificates = nil + } if option.StorageStatePath != nil { var storageState *OptionalStorageState storageString, err := os.ReadFile(*options[0].StorageStatePath) @@ -78,7 +88,7 @@ func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserCo } channel, err := b.channel.Send("newContext", options, overrides) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } context := fromChannel(channel).(*browserContextImpl) context.browser = b @@ -107,7 +117,7 @@ func (b *browserImpl) NewPage(options ...BrowserNewPageOptions) (Page, error) { func (b *browserImpl) NewBrowserCDPSession() (CDPSession, error) { channel, err := b.channel.Send("newBrowserCDPSession") if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } cdpSession := fromChannel(channel).(*cdpSessionImpl) @@ -121,19 +131,22 @@ func (b *browserImpl) Contexts() []BrowserContext { return b.contexts } -func (b *browserImpl) Close() error { - if b.isClosedOrClosing { - return nil - } - b.Lock() - b.isClosedOrClosing = true - b.Unlock() - _, err := b.channel.Send("close") - if err != nil && !isSafeCloseError(err) { - return fmt.Errorf("close browser failed: %w", err) +func (b *browserImpl) Close(options ...BrowserCloseOptions) (err error) { + if len(options) == 1 { + b.closeReason = options[0].Reason } + if b.shouldCloseConnectionOnClose { - return b.connection.Stop(errMsgBrowserClosed) + err = b.connection.Stop() + } else if b.closeReason != nil { + _, err = b.channel.Send("close", map[string]interface{}{ + "reason": b.closeReason, + }) + } else { + _, err = b.channel.Send("close") + } + if err != nil && !errors.Is(err, ErrTargetClosed) { + return fmt.Errorf("close browser failed: %w", err) } return nil } @@ -175,11 +188,11 @@ func (b *browserImpl) StopTracing() ([]byte, error) { return binary, err } if b.chromiumTracingPath != nil { - err := os.MkdirAll(filepath.Dir(*b.chromiumTracingPath), 0777) + err := os.MkdirAll(filepath.Dir(*b.chromiumTracingPath), 0o777) if err != nil { return binary, err } - err = os.WriteFile(*b.chromiumTracingPath, binary, 0644) + err = os.WriteFile(*b.chromiumTracingPath, binary, 0o644) if err != nil { return binary, err } @@ -189,7 +202,6 @@ func (b *browserImpl) StopTracing() ([]byte, error) { func (b *browserImpl) onClose() { b.Lock() - b.isClosedOrClosing = true if b.isConnected { b.isConnected = false b.Unlock() @@ -214,3 +226,49 @@ func newBrowser(parent *channelOwner, objectType string, guid string, initialize b.channel.On("close", b.onClose) return b } + +func transformClientCertificate(clientCertificates []ClientCertificate) ([]map[string]interface{}, error) { + results := make([]map[string]interface{}, 0) + + for _, cert := range clientCertificates { + data := map[string]interface{}{ + "origin": cert.Origin, + "passphrase": cert.Passphrase, + } + if len(cert.Cert) > 0 { + data["cert"] = base64.StdEncoding.EncodeToString(cert.Cert) + } else if cert.CertPath != nil { + content, err := os.ReadFile(*cert.CertPath) + if err != nil { + return nil, err + } + data["cert"] = base64.StdEncoding.EncodeToString(content) + } + + if len(cert.Key) > 0 { + data["key"] = base64.StdEncoding.EncodeToString(cert.Key) + } else if cert.KeyPath != nil { + content, err := os.ReadFile(*cert.KeyPath) + if err != nil { + return nil, err + } + data["key"] = base64.StdEncoding.EncodeToString(content) + } + + if len(cert.Pfx) > 0 { + data["pfx"] = base64.StdEncoding.EncodeToString(cert.Pfx) + } else if cert.PfxPath != nil { + content, err := os.ReadFile(*cert.PfxPath) + if err != nil { + return nil, err + } + data["pfx"] = base64.StdEncoding.EncodeToString(content) + } + + results = append(results, data) + } + if len(results) == 0 { + return nil, nil + } + return results, nil +} diff --git a/vendor/github.com/playwright-community/playwright-go/browser_context.go b/vendor/github.com/playwright-community/playwright-go/browser_context.go index 19c29c4d6..2733bad52 100644 --- a/vendor/github.com/playwright-community/playwright-go/browser_context.go +++ b/vendor/github.com/playwright-community/playwright-go/browser_context.go @@ -4,38 +4,57 @@ import ( "encoding/json" "errors" "fmt" - "log" "os" + "regexp" "strings" + "sync" + + "github.com/playwright-community/playwright-go/internal/safe" + "golang.org/x/exp/slices" ) type browserContextImpl struct { channelOwner - timeoutSettings *timeoutSettings - isClosedOrClosing bool - options *BrowserNewContextOptions - pages []Page - routes []*routeHandlerEntry - ownedPage Page - browser *browserImpl - serviceWorkers []Worker - backgroundPages []Page - bindings map[string]BindingCallFunction - tracing *tracingImpl - request *apiRequestContextImpl - harRecorders map[string]harRecordingMetadata - closed chan struct{} + timeoutSettings *timeoutSettings + closeWasCalled bool + options *BrowserNewContextOptions + pages []Page + routes []*routeHandlerEntry + ownedPage Page + browser *browserImpl + serviceWorkers []Worker + backgroundPages []Page + bindings *safe.SyncMap[string, BindingCallFunction] + tracing *tracingImpl + request *apiRequestContextImpl + harRecorders map[string]harRecordingMetadata + closed chan struct{} + closeReason *string + harRouters []*harRouter + clock Clock +} + +func (b *browserContextImpl) Clock() Clock { + return b.clock } func (b *browserContextImpl) SetDefaultNavigationTimeout(timeout float64) { - b.timeoutSettings.SetDefaultNavigationTimeout(&timeout) + b.setDefaultNavigationTimeoutImpl(&timeout) +} + +func (b *browserContextImpl) setDefaultNavigationTimeoutImpl(timeout *float64) { + b.timeoutSettings.SetDefaultNavigationTimeout(timeout) b.channel.SendNoReply("setDefaultNavigationTimeoutNoReply", map[string]interface{}{ "timeout": timeout, }) } func (b *browserContextImpl) SetDefaultTimeout(timeout float64) { - b.timeoutSettings.SetDefaultTimeout(&timeout) + b.setDefaultTimeoutImpl(&timeout) +} + +func (b *browserContextImpl) setDefaultTimeoutImpl(timeout *float64) { + b.timeoutSettings.SetDefaultTimeout(timeout) b.channel.SendNoReply("setDefaultTimeoutNoReply", map[string]interface{}{ "timeout": timeout, }) @@ -50,6 +69,7 @@ func (b *browserContextImpl) Pages() []Page { func (b *browserContextImpl) Browser() Browser { return b.browser } + func (b *browserContextImpl) Tracing() Tracing { return b.tracing } @@ -67,7 +87,7 @@ func (b *browserContextImpl) NewCDPSession(page interface{}) (CDPSession, error) channel, err := b.channel.Send("newCDPSession", params) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } cdpSession := fromChannel(channel).(*cdpSessionImpl) @@ -81,7 +101,7 @@ func (b *browserContextImpl) NewPage() (Page, error) { } channel, err := b.channel.Send("newPage") if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } return fromChannel(channel).(*pageImpl), nil } @@ -91,7 +111,7 @@ func (b *browserContextImpl) Cookies(urls ...string) ([]Cookie, error) { "urls": urls, }) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } cookies := make([]Cookie, len(result.([]interface{}))) for i, item := range result.([]interface{}) { @@ -109,8 +129,53 @@ func (b *browserContextImpl) AddCookies(cookies []OptionalCookie) error { return err } -func (b *browserContextImpl) ClearCookies() error { - _, err := b.channel.Send("clearCookies") +func (b *browserContextImpl) ClearCookies(options ...BrowserContextClearCookiesOptions) error { + params := map[string]interface{}{} + if len(options) == 1 { + if options[0].Domain != nil { + switch t := options[0].Domain.(type) { + case string: + params["domain"] = t + case *string: + params["domain"] = t + case *regexp.Regexp: + pattern, flag := convertRegexp(t) + params["domainRegexSource"] = pattern + params["domainRegexFlags"] = flag + default: + return errors.New("invalid type for domain, expected string or *regexp.Regexp") + } + } + if options[0].Name != nil { + switch t := options[0].Name.(type) { + case string: + params["name"] = t + case *string: + params["name"] = t + case *regexp.Regexp: + pattern, flag := convertRegexp(t) + params["nameRegexSource"] = pattern + params["nameRegexFlags"] = flag + default: + return errors.New("invalid type for name, expected string or *regexp.Regexp") + } + } + if options[0].Path != nil { + switch t := options[0].Path.(type) { + case string: + params["path"] = t + case *string: + params["path"] = t + case *regexp.Regexp: + pattern, flag := convertRegexp(t) + params["pathRegexSource"] = pattern + params["pathRegexFlags"] = flag + default: + return errors.New("invalid type for path, expected string or *regexp.Regexp") + } + } + } + _, err := b.channel.Send("clearCookies", params) return err } @@ -176,18 +241,21 @@ func (b *browserContextImpl) ExposeBinding(name string, binding BindingCallFunct needsHandle = handle[0] } for _, page := range b.Pages() { - if _, ok := page.(*pageImpl).bindings[name]; ok { + if _, ok := page.(*pageImpl).bindings.Load(name); ok { return fmt.Errorf("Function '%s' has been already registered in one of the pages", name) } } - if _, ok := b.bindings[name]; ok { + if _, ok := b.bindings.Load(name); ok { return fmt.Errorf("Function '%s' has been already registered", name) } - b.bindings[name] = binding _, err := b.channel.Send("exposeBinding", map[string]interface{}{ "name": name, "needsHandle": needsHandle, }) + if err != nil { + return err + } + b.bindings.Store(name, binding) return err } @@ -198,21 +266,56 @@ func (b *browserContextImpl) ExposeFunction(name string, binding ExposedFunction } func (b *browserContextImpl) Route(url interface{}, handler routeHandler, times ...int) error { - b.routes = append(b.routes, newRouteHandlerEntry(newURLMatcher(url, b.options.BaseURL), handler, times...)) + b.Lock() + defer b.Unlock() + b.routes = slices.Insert(b.routes, 0, newRouteHandlerEntry(newURLMatcher(url, b.options.BaseURL), handler, times...)) return b.updateInterceptionPatterns() } func (b *browserContextImpl) Unroute(url interface{}, handlers ...routeHandler) error { + removed, remaining, err := unroute(b.routes, url, handlers...) + if err != nil { + return err + } + return b.unrouteInternal(removed, remaining, UnrouteBehaviorDefault) +} + +func (b *browserContextImpl) unrouteInternal(removed []*routeHandlerEntry, remaining []*routeHandlerEntry, behavior *UnrouteBehavior) error { b.Lock() defer b.Unlock() - - routes, err := unroute(b.routes, url, handlers...) - if err != nil { + b.routes = remaining + if err := b.updateInterceptionPatterns(); err != nil { return err } - b.routes = routes + if behavior == nil || behavior == UnrouteBehaviorDefault { + return nil + } + wg := &sync.WaitGroup{} + for _, entry := range removed { + wg.Add(1) + go func(entry *routeHandlerEntry) { + defer wg.Done() + entry.Stop(string(*behavior)) + }(entry) + } + wg.Wait() + return nil +} - return b.updateInterceptionPatterns() +func (b *browserContextImpl) UnrouteAll(options ...BrowserContextUnrouteAllOptions) error { + var behavior *UnrouteBehavior + if len(options) == 1 { + behavior = options[0].Behavior + } + defer b.disposeHarRouters() + return b.unrouteInternal(b.routes, []*routeHandlerEntry{}, behavior) +} + +func (b *browserContextImpl) disposeHarRouters() { + for _, router := range b.harRouters { + router.dispose() + } + b.harRouters = make([]*harRouter, 0) } func (b *browserContextImpl) Request() APIRequestContext { @@ -243,6 +346,7 @@ func (b *browserContextImpl) RouteFromHAR(har string, options ...BrowserContextR notFound = HarNotFoundAbort } router := newHarRouter(b.connection.localUtils, har, *notFound, opt.URL) + b.harRouters = append(b.harRouters, router) return router.addContextRoute(b) } @@ -260,7 +364,7 @@ func (b *browserContextImpl) waiterForEvent(event string, options ...BrowserCont predicate = options[0].Predicate } waiter := newWaiter().WithTimeout(timeout) - waiter.RejectOnEvent(b, "close", errors.New("context closed")) + waiter.RejectOnEvent(b, "close", ErrTargetClosed) return waiter.WaitForEvent(b, event, predicate) } @@ -305,13 +409,24 @@ func (b *browserContextImpl) ExpectPage(cb func() error, options ...BrowserConte return ret.(Page), nil } -func (b *browserContextImpl) Close() error { - if b.isClosedOrClosing { +func (b *browserContextImpl) Close(options ...BrowserContextCloseOptions) error { + if b.closeWasCalled { return nil } - b.Lock() - b.isClosedOrClosing = true - b.Unlock() + if len(options) == 1 { + b.closeReason = options[0].Reason + } + b.closeWasCalled = true + + _, err := b.channel.connection.WrapAPICall(func() (interface{}, error) { + return nil, b.request.Dispose(APIRequestContextDisposeOptions{ + Reason: b.closeReason, + }) + }, true) + if err != nil { + return err + } + innerClose := func() (interface{}, error) { for harId, harMetaData := range b.harRecorders { overrides := map[string]interface{}{} @@ -346,12 +461,17 @@ func (b *browserContextImpl) Close() error { return nil, nil } - _, err := b.channel.connection.WrapAPICall(innerClose, true) + _, err = b.channel.connection.WrapAPICall(innerClose, true) if err != nil { return err } - _, err = b.channel.Send("close") + _, err = b.channel.Send("close", map[string]interface{}{ + "reason": b.closeReason, + }) + if err != nil { + return err + } <-b.closed return err } @@ -417,11 +537,11 @@ func (b *browserContextImpl) StorageState(paths ...string) (*StorageState, error } func (b *browserContextImpl) onBinding(binding *bindingCallImpl) { - function := b.bindings[binding.initializer["name"].(string)] - if function == nil { + function, ok := b.bindings.Load(binding.initializer["name"].(string)) + if !ok || function == nil { return } - go binding.Call(function) + binding.Call(function) } func (b *browserContextImpl) onClose() { @@ -436,6 +556,7 @@ func (b *browserContextImpl) onClose() { b.browser.contexts = contexts b.browser.Unlock() } + b.disposeHarRouters() b.Emit("close", b) } @@ -453,37 +574,55 @@ func (b *browserContextImpl) onPage(page Page) { func (b *browserContextImpl) onRoute(route *routeImpl) { go func() { b.Lock() - defer b.Unlock() route.context = b + page := route.Request().(*requestImpl).safePage() routes := make([]*routeHandlerEntry, len(b.routes)) copy(routes, b.routes) + b.Unlock() - url := route.Request().URL() - for i, handlerEntry := range routes { - if !handlerEntry.Matches(url) { - continue - } - if handlerEntry.WillExceed() { - b.routes = append(b.routes[:i], b.routes[i+1:]...) - } - handled := handlerEntry.Handle(route) + checkInterceptionIfNeeded := func() { + b.Lock() + defer b.Unlock() if len(b.routes) == 0 { _, err := b.connection.WrapAPICall(func() (interface{}, error) { err := b.updateInterceptionPatterns() return nil, err }, true) if err != nil { - log.Printf("could not update interception patterns: %v", err) + logger.Printf("could not update interception patterns: %v\n", err) } } + } + + url := route.Request().URL() + for _, handlerEntry := range routes { + // If the page or the context was closed we stall all requests right away. + if (page != nil && page.closeWasCalled) || b.closeWasCalled { + return + } + if !handlerEntry.Matches(url) { + continue + } + if !slices.ContainsFunc(b.routes, func(entry *routeHandlerEntry) bool { + return entry == handlerEntry + }) { + continue + } + if handlerEntry.WillExceed() { + b.routes = slices.DeleteFunc(b.routes, func(rhe *routeHandlerEntry) bool { + return rhe == handlerEntry + }) + } + handled := handlerEntry.Handle(route) + checkInterceptionIfNeeded() yes := <-handled if yes { return } } - if err := route.internalContinue(true); err != nil { - log.Printf("could not continue request: %v", err) - } + // If the page is closed or unrouteAll() was called without waiting and interception disabled, + // the method will throw an error - silence it. + _ = route.internalContinue(true) }() } @@ -547,6 +686,10 @@ func (b *browserContextImpl) ServiceWorkers() []Worker { return b.serviceWorkers } +func (b *browserContextImpl) OnBackgroundPage(fn func(Page)) { + b.On("backgroundpage", fn) +} + func (b *browserContextImpl) OnClose(fn func(BrowserContext)) { b.On("close", fn) } @@ -583,15 +726,28 @@ func (b *browserContextImpl) OnWebError(fn func(WebError)) { b.On("weberror", fn) } +func (b *browserContextImpl) effectiveCloseReason() *string { + b.Lock() + defer b.Unlock() + if b.closeReason != nil { + return b.closeReason + } + if b.browser != nil { + return b.browser.closeReason + } + return nil +} + func newBrowserContext(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserContextImpl { bt := &browserContextImpl{ timeoutSettings: newTimeoutSettings(nil), pages: make([]Page, 0), backgroundPages: make([]Page, 0), routes: make([]*routeHandlerEntry, 0), - bindings: make(map[string]BindingCallFunction), + bindings: safe.NewSyncMap[string, BindingCallFunction](), harRecorders: make(map[string]harRecordingMetadata), closed: make(chan struct{}, 1), + harRouters: make([]*harRouter, 0), } bt.createChannelOwner(bt, parent, objectType, guid, initializer) if parent.objectType == "Browser" { @@ -600,8 +756,9 @@ func newBrowserContext(parent *channelOwner, objectType string, guid string, ini } bt.tracing = fromChannel(initializer["tracing"]).(*tracingImpl) bt.request = fromChannel(initializer["requestContext"]).(*apiRequestContextImpl) + bt.clock = newClock(bt) bt.channel.On("bindingCall", func(params map[string]interface{}) { - bt.onBinding(fromChannel(params["binding"]).(*bindingCallImpl)) + go bt.onBinding(fromChannel(params["binding"]).(*bindingCallImpl)) }) bt.channel.On("close", bt.onClose) @@ -647,8 +804,9 @@ func newBrowserContext(parent *channelOwner, objectType string, guid string, ini }) bt.channel.On( "pageError", func(ev map[string]interface{}) { - err := &Error{} - remapMapToStruct(ev["error"].(map[string]interface{})["error"], err) + pwErr := &Error{} + remapMapToStruct(ev["error"].(map[string]interface{})["error"], pwErr) + err := parseError(*pwErr) page := fromNullableChannel(ev["page"]) if page != nil { bt.Emit("weberror", newWebError(page.(*pageImpl), err)) diff --git a/vendor/github.com/playwright-community/playwright-go/browser_type.go b/vendor/github.com/playwright-community/playwright-go/browser_type.go index 23c87dc3d..fd160b71f 100644 --- a/vendor/github.com/playwright-community/playwright-go/browser_type.go +++ b/vendor/github.com/playwright-community/playwright-go/browser_type.go @@ -25,7 +25,7 @@ func (b *browserTypeImpl) Launch(options ...BrowserTypeLaunchOptions) (Browser, } channel, err := b.channel.Send("launch", options, overrides) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } browser := fromChannel(channel).(*browserImpl) b.didLaunchBrowser(browser) @@ -52,6 +52,14 @@ func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options .. } options[0].AcceptDownloads = nil } + if options[0].ClientCertificates != nil { + certs, err := transformClientCertificate(options[0].ClientCertificates) + if err != nil { + return nil, err + } + overrides["clientCertificates"] = certs + options[0].ClientCertificates = nil + } if options[0].ExtraHttpHeaders != nil { overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders) options[0].ExtraHttpHeaders = nil @@ -81,12 +89,13 @@ func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options .. } channel, err := b.channel.Send("launchPersistentContext", options, overrides) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } context := fromChannel(channel).(*browserContextImpl) b.didCreateContext(context, option, tracesDir) return context, nil } + func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConnectOptions) (Browser, error) { overrides := map[string]interface{}{ "wsEndpoint": wsEndpoint, @@ -97,9 +106,15 @@ func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConne return nil, err } jsonPipe := fromChannel(pipe.(map[string]interface{})["pipe"]).(*jsonPipe) - connection := newConnection(jsonPipe.Close, localUtils) - connection.isRemote = true - var browser *browserImpl + connection := newConnection(jsonPipe, localUtils) + + playwright, err := connection.Start() + if err != nil { + return nil, err + } + playwright.setSelectors(b.playwright.Selectors) + browser := fromChannel(playwright.initializer["preLaunchedBrowser"]).(*browserImpl) + browser.shouldCloseConnectionOnClose = true pipeClosed := func() { for _, context := range browser.Contexts() { pages := context.Pages() @@ -109,21 +124,10 @@ func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConne context.(*browserContextImpl).onClose() } browser.onClose() - connection.cleanup(errMsgBrowserClosed) + connection.cleanup() } jsonPipe.On("closed", pipeClosed) - connection.onmessage = func(message map[string]interface{}) error { - if err := jsonPipe.Send(message); err != nil { - pipeClosed() - return err - } - return nil - } - jsonPipe.On("message", connection.Dispatch) - playwright := connection.Start() - playwright.setSelectors(b.playwright.Selectors) - browser = fromChannel(playwright.initializer["preLaunchedBrowser"]).(*browserImpl) - browser.shouldCloseConnectionOnClose = true + b.didLaunchBrowser(browser) return browser, nil } diff --git a/vendor/github.com/playwright-community/playwright-go/channel.go b/vendor/github.com/playwright-community/playwright-go/channel.go index 0499368f2..81ec21600 100644 --- a/vendor/github.com/playwright-community/playwright-go/channel.go +++ b/vendor/github.com/playwright-community/playwright-go/channel.go @@ -1,10 +1,5 @@ package playwright -import ( - "log" - "reflect" -) - type channel struct { eventEmitter guid string @@ -41,14 +36,11 @@ func (c *channel) innerSend(method string, returnAsDict bool, options ...interfa if returnAsDict { return result, nil } - if reflect.TypeOf(result).Kind() == reflect.Map { - mapV := result.(map[string]interface{}) - if len(mapV) == 0 { - return nil, nil - } + if mapV, ok := result.(map[string]interface{}); ok && len(mapV) <= 1 { for key := range mapV { return mapV[key], nil } + return nil, nil } return result, nil } @@ -59,7 +51,7 @@ func (c *channel) SendNoReply(method string, options ...interface{}) { return c.connection.sendMessageToServer(c.owner, method, params, true) }, false) if err != nil { - log.Printf("SendNoReply failed: %v", err) + logger.Printf("SendNoReply failed: %v\n", err) } } @@ -70,6 +62,5 @@ func newChannel(owner *channelOwner, object interface{}) *channel { owner: owner, object: object, } - channel.initEventEmitter() return channel } diff --git a/vendor/github.com/playwright-community/playwright-go/channel_owner.go b/vendor/github.com/playwright-community/playwright-go/channel_owner.go index 6c6114990..007be70e5 100644 --- a/vendor/github.com/playwright-community/playwright-go/channel_owner.go +++ b/vendor/github.com/playwright-community/playwright-go/channel_owner.go @@ -23,7 +23,7 @@ func (c *channelOwner) dispose(reason ...string) { if c.parent != nil { delete(c.parent.objects, c.guid) } - delete(c.connection.objects, c.guid) + c.connection.objects.Delete(c.guid) if len(reason) > 0 { c.wasCollected = reason[0] == "gc" } @@ -89,11 +89,10 @@ func (c *channelOwner) createChannelOwner(self interface{}, parent *channelOwner c.parent.objects[guid] = c } if c.connection != nil { - c.connection.objects[guid] = c + c.connection.objects.Store(guid, c) } c.channel = newChannel(c, self) c.eventToSubscriptionMapping = map[string]string{} - c.initEventEmitter() } type rootChannelOwner struct { diff --git a/vendor/github.com/playwright-community/playwright-go/clock.go b/vendor/github.com/playwright-community/playwright-go/clock.go new file mode 100644 index 000000000..8bab03740 --- /dev/null +++ b/vendor/github.com/playwright-community/playwright-go/clock.go @@ -0,0 +1,111 @@ +package playwright + +import ( + "errors" + "time" +) + +type clockImpl struct { + browserCtx *browserContextImpl +} + +func newClock(bCtx *browserContextImpl) Clock { + return &clockImpl{ + browserCtx: bCtx, + } +} + +func (c *clockImpl) FastForward(ticks interface{}) error { + params, err := parseTicks(ticks) + if err != nil { + return err + } + + _, err = c.browserCtx.channel.Send("clockFastForward", params) + return err +} + +func (c *clockImpl) Install(options ...ClockInstallOptions) (err error) { + params := map[string]any{} + if len(options) == 1 { + if options[0].Time != nil { + params, err = parseTime(options[0].Time) + if err != nil { + return err + } + } + } + + _, err = c.browserCtx.channel.Send("clockInstall", params) + + return err +} + +func (c *clockImpl) PauseAt(time interface{}) error { + params, err := parseTime(time) + if err != nil { + return err + } + + _, err = c.browserCtx.channel.Send("clockPauseAt", params) + return err +} + +func (c *clockImpl) Resume() error { + _, err := c.browserCtx.channel.Send("clockResume") + return err +} + +func (c *clockImpl) RunFor(ticks interface{}) error { + params, err := parseTicks(ticks) + if err != nil { + return err + } + + _, err = c.browserCtx.channel.Send("clockRunFor", params) + return err +} + +func (c *clockImpl) SetFixedTime(time interface{}) error { + params, err := parseTime(time) + if err != nil { + return err + } + + _, err = c.browserCtx.channel.Send("clockSetFixedTime", params) + return err +} + +func (c *clockImpl) SetSystemTime(time interface{}) error { + params, err := parseTime(time) + if err != nil { + return err + } + + _, err = c.browserCtx.channel.Send("clockSetSystemTime", params) + return err +} + +func parseTime(t interface{}) (map[string]any, error) { + switch v := t.(type) { + case int, int64: + return map[string]any{"timeNumber": v}, nil + case string: + return map[string]any{"timeString": v}, nil + case time.Time: + return map[string]any{"timeNumber": v.UnixMilli()}, nil + default: + return nil, errors.New("time should be one of: int, int64, string, time.Time") + } +} + +func parseTicks(ticks interface{}) (map[string]any, error) { + switch v := ticks.(type) { + case int, int64: + return map[string]any{"ticksNumber": v}, nil + case string: + return map[string]any{"ticksString": v}, nil + default: + return nil, errors.New("ticks should be one of: int, int64, string") + } +} diff --git a/vendor/github.com/playwright-community/playwright-go/connection.go b/vendor/github.com/playwright-community/playwright-go/connection.go index 19a43da59..654096736 100644 --- a/vendor/github.com/playwright-community/playwright-go/connection.go +++ b/vendor/github.com/playwright-community/playwright-go/connection.go @@ -3,7 +3,6 @@ package playwright import ( "errors" "fmt" - "log" "reflect" "regexp" "strconv" @@ -13,6 +12,7 @@ import ( "time" "github.com/go-stack/stack" + "github.com/playwright-community/playwright-go/internal/safe" ) var ( @@ -26,82 +26,93 @@ type result struct { } type connection struct { + transport transport apiZone sync.Map - objects map[string]*channelOwner - lastID int - lastIDLock sync.Mutex + objects *safe.SyncMap[string, *channelOwner] + lastID atomic.Uint32 rootObject *rootChannelOwner - callbacks sync.Map + callbacks *safe.SyncMap[uint32, *protocolCallback] afterClose func() onClose func() error - onmessage func(map[string]interface{}) error isRemote bool localUtils *localUtilsImpl tracingCount atomic.Int32 abort chan struct{} - closedError atomic.Value + abortOnce sync.Once + closedError *safeValue[error] } -func (c *connection) Start() *Playwright { - playwright := make(chan *Playwright, 1) +func (c *connection) Start() (*Playwright, error) { go func() { - pw, err := c.rootObject.initialize() - if err != nil { - log.Fatal(err) - return + for { + msg, err := c.transport.Poll() + if err != nil { + _ = c.transport.Close() + c.cleanup(err) + return + } + c.Dispatch(msg) } - playwright <- pw }() - return <-playwright + + c.onClose = func() error { + if err := c.transport.Close(); err != nil { + return err + } + return nil + } + + return c.rootObject.initialize() } -func (c *connection) Stop(errMsg ...string) error { - err := c.onClose() - if err != nil { +func (c *connection) Stop() error { + if err := c.onClose(); err != nil { return err } - c.cleanup(errMsg...) + c.cleanup() return nil } -func (c *connection) cleanup(errMsg ...string) { - if len(errMsg) == 0 { - c.closedError.Store(errors.New("connection closed")) +func (c *connection) cleanup(cause ...error) { + if len(cause) > 0 { + c.closedError.Set(fmt.Errorf("%w: %w", ErrTargetClosed, cause[0])) } else { - c.closedError.Store(errors.New(errMsg[0])) + c.closedError.Set(ErrTargetClosed) } if c.afterClose != nil { c.afterClose() } - select { - case <-c.abort: - default: - close(c.abort) - } + c.abortOnce.Do(func() { + select { + case <-c.abort: + default: + close(c.abort) + } + }) } func (c *connection) Dispatch(msg *message) { - if c.closedError.Load() != nil { + if c.closedError.Get() != nil { return } method := msg.Method if msg.ID != 0 { - cb, _ := c.callbacks.LoadAndDelete(msg.ID) - if cb.(*protocolCallback).noReply { + cb, _ := c.callbacks.LoadAndDelete(uint32(msg.ID)) + if cb.noReply { return } if msg.Error != nil { - cb.(*protocolCallback).SetResult(result{ + cb.SetResult(result{ Error: parseError(msg.Error.Error), }) } else { - cb.(*protocolCallback).SetResult(result{ + cb.SetResult(result{ Data: c.replaceGuidsWithChannels(msg.Result), }) } return } - object := c.objects[msg.GUID] + object, _ := c.objects.Load(msg.GUID) if method == "__create__" { c.createRemoteObject( object, msg.Params["type"].(string), msg.Params["guid"].(string), msg.Params["initializer"], @@ -112,7 +123,7 @@ func (c *connection) Dispatch(msg *message) { return } if method == "__adopt__" { - child, ok := c.objects[msg.Params["guid"].(string)] + child, ok := c.objects.Load(msg.Params["guid"].(string)) if !ok { return } @@ -195,7 +206,7 @@ func (c *connection) replaceGuidsWithChannels(payload interface{}) interface{} { if v.Kind() == reflect.Map { mapV := payload.(map[string]interface{}) if guid, hasGUID := mapV["guid"]; hasGUID { - if channelOwner, ok := c.objects[guid.(string)]; ok { + if channelOwner, ok := c.objects.Load(guid.(string)); ok { return channelOwner.channel } } @@ -208,17 +219,14 @@ func (c *connection) replaceGuidsWithChannels(payload interface{}) interface{} { } func (c *connection) sendMessageToServer(object *channelOwner, method string, params interface{}, noReply bool) (*protocolCallback, error) { - if e := c.closedError.Load(); e != nil { - return nil, e.(error) + if err := c.closedError.Get(); err != nil { + return nil, err } if object.wasCollected { return nil, errors.New("The object has been collected to prevent unbounded heap growth.") } - c.lastIDLock.Lock() - c.lastID++ - id := c.lastID - c.lastIDLock.Unlock() + id := c.lastID.Add(1) cb, _ := c.callbacks.LoadOrStore(id, newProtocolCallback(noReply, c.abort)) var ( metadata = make(map[string]interface{}, 0) @@ -231,7 +239,7 @@ func (c *connection) sendMessageToServer(object *channelOwner, method string, pa } stack = append(stack, apiZone.(parsedStackTrace).frames...) } - metadata["wallTime"] = time.Now().Nanosecond() + metadata["wallTime"] = time.Now().UnixMilli() message := map[string]interface{}{ "id": id, "guid": object.guid, @@ -243,11 +251,11 @@ func (c *connection) sendMessageToServer(object *channelOwner, method string, pa c.LocalUtils().AddStackToTracingNoReply(id, stack) } - if err := c.onmessage(message); err != nil { + if err := c.transport.Send(message); err != nil { return nil, fmt.Errorf("could not send message: %w", err) } - return cb.(*protocolCallback), nil + return cb, nil } func (c *connection) setInTracing(isTracing bool) { @@ -317,15 +325,18 @@ func serializeCallLocation(caller stack.Call) map[string]interface{} { } } -func newConnection(onClose func() error, localUtils ...*localUtilsImpl) *connection { +func newConnection(transport transport, localUtils ...*localUtilsImpl) *connection { connection := &connection{ - abort: make(chan struct{}, 1), - objects: make(map[string]*channelOwner), - onClose: onClose, - isRemote: false, + abort: make(chan struct{}, 1), + callbacks: safe.NewSyncMap[uint32, *protocolCallback](), + objects: safe.NewSyncMap[string, *channelOwner](), + transport: transport, + isRemote: false, + closedError: &safeValue[error]{}, } if len(localUtils) > 0 { connection.localUtils = localUtils[0] + connection.isRemote = true } connection.rootObject = newRootChannelOwner(connection) return connection @@ -343,7 +354,7 @@ func fromNullableChannel(v interface{}) interface{} { } type protocolCallback struct { - Callback chan result + callback chan result noReply bool abort <-chan struct{} } @@ -354,8 +365,12 @@ func (pc *protocolCallback) SetResult(r result) { } select { case <-pc.abort: + select { + case pc.callback <- r: + default: + } return - case pc.Callback <- r: + case pc.callback <- r: } } @@ -364,10 +379,15 @@ func (pc *protocolCallback) GetResult() (interface{}, error) { return nil, nil } select { - case result := <-pc.Callback: + case result := <-pc.callback: return result.Data, result.Error case <-pc.abort: - return nil, errors.New("Connection closed") + select { + case result := <-pc.callback: + return result.Data, result.Error + default: + return nil, errors.New("Connection closed") + } } } @@ -379,7 +399,7 @@ func newProtocolCallback(noReply bool, abort <-chan struct{}) *protocolCallback } } return &protocolCallback{ - Callback: make(chan result), + callback: make(chan result, 1), abort: abort, } } diff --git a/vendor/github.com/playwright-community/playwright-go/element_handle.go b/vendor/github.com/playwright-community/playwright-go/element_handle.go index 51a77105c..a44ae89ff 100644 --- a/vendor/github.com/playwright-community/playwright-go/element_handle.go +++ b/vendor/github.com/playwright-community/playwright-go/element_handle.go @@ -2,6 +2,7 @@ package playwright import ( "encoding/base64" + "errors" "fmt" "os" ) @@ -166,10 +167,20 @@ func (e *elementHandleImpl) ScrollIntoViewIfNeeded(options ...ElementHandleScrol return err } -func (e *elementHandleImpl) SetInputFiles(files []InputFile, options ...ElementHandleSetInputFilesOptions) error { - _, err := e.channel.Send("setInputFiles", map[string]interface{}{ - "files": normalizeFilePayloads(files), - }, options) +func (e *elementHandleImpl) SetInputFiles(files interface{}, options ...ElementHandleSetInputFilesOptions) error { + frame, err := e.OwnerFrame() + if err != nil { + return err + } + if frame == nil { + return errors.New("Cannot set input files to detached element") + } + + params, err := convertInputFiles(files, frame.(*frameImpl).page.browserContext) + if err != nil { + return err + } + _, err = e.channel.Send("setInputFiles", params, options) return err } @@ -250,14 +261,14 @@ func (e *elementHandleImpl) Screenshot(options ...ElementHandleScreenshotOptions } data, err := e.channel.Send("screenshot", options, overrides) if err != nil { - return nil, fmt.Errorf("could not send message :%w", err) + return nil, err } image, err := base64.StdEncoding.DecodeString(data.(string)) if err != nil { return nil, fmt.Errorf("could not decode base64 :%w", err) } if path != nil { - if err := os.WriteFile(*path, image, 0644); err != nil { + if err := os.WriteFile(*path, image, 0o644); err != nil { return nil, err } } @@ -376,18 +387,6 @@ func newElementHandle(parent *channelOwner, objectType string, guid string, init return bt } -func normalizeFilePayloads(files []InputFile) []map[string]string { - out := make([]map[string]string, 0) - for _, file := range files { - out = append(out, map[string]string{ - "name": file.Name, - "mimeType": file.MimeType, - "buffer": base64.StdEncoding.EncodeToString(file.Buffer), - }) - } - return out -} - func transformToStringList(in interface{}) []string { s := in.([]interface{}) diff --git a/vendor/github.com/playwright-community/playwright-go/errors.go b/vendor/github.com/playwright-community/playwright-go/errors.go index e822cbd10..36f7396bb 100644 --- a/vendor/github.com/playwright-community/playwright-go/errors.go +++ b/vendor/github.com/playwright-community/playwright-go/errors.go @@ -1,6 +1,20 @@ package playwright -import "strings" +import ( + "errors" + "fmt" +) + +var ( + // ErrPlaywright wraps all Playwright errors. + // - Use errors.Is to check if the error is a Playwright error. + // - Use errors.As to cast an error to [Error] if you want to access "Stack". + ErrPlaywright = errors.New("playwright") + // ErrTargetClosed usually wraps a reason. + ErrTargetClosed = errors.New("target closed") + // ErrTimeout wraps timeout errors. It can be either Playwright TimeoutError or client timeout. + ErrTimeout = errors.New("timeout") +) // Error represents a Playwright error type Error struct { @@ -27,27 +41,18 @@ func (e *Error) Is(target error) bool { return e.Message == err.Message } -// TimeoutError represents a Playwright TimeoutError -var TimeoutError = &Error{ - Name: "TimeoutError", -} - func parseError(err Error) error { - return &Error{ - Name: err.Name, - Message: err.Message, - Stack: err.Stack, + if err.Name == "TimeoutError" { + return fmt.Errorf("%w: %w: %w", ErrPlaywright, ErrTimeout, &err) + } else if err.Name == "TargetClosedError" { + return fmt.Errorf("%w: %w: %w", ErrPlaywright, ErrTargetClosed, &err) } + return fmt.Errorf("%w: %w", ErrPlaywright, &err) } -const ( - errMsgBrowserClosed = "Browser has been closed" - errMsgBrowserOrContextClosed = "Target page, context or browser has been closed" -) - -func isSafeCloseError(err error) bool { - if err == nil { - return false +func targetClosedError(reason *string) error { + if reason == nil { + return ErrTargetClosed } - return strings.HasSuffix(err.Error(), errMsgBrowserClosed) || strings.HasSuffix(err.Error(), errMsgBrowserOrContextClosed) + return fmt.Errorf("%w: %s", ErrTargetClosed, *reason) } diff --git a/vendor/github.com/playwright-community/playwright-go/event_emitter.go b/vendor/github.com/playwright-community/playwright-go/event_emitter.go index 0c2a9f8fb..3bfd9c2f8 100644 --- a/vendor/github.com/playwright-community/playwright-go/event_emitter.go +++ b/vendor/github.com/playwright-community/playwright-go/event_emitter.go @@ -4,6 +4,8 @@ import ( "math" "reflect" "sync" + + "golang.org/x/exp/slices" ) type EventEmitter interface { @@ -15,45 +17,32 @@ type EventEmitter interface { } type ( - eventRegister struct { - once []interface{} - on []interface{} - } eventEmitter struct { eventsMutex sync.Mutex events map[string]*eventRegister + hasInit bool } -) - -func (e *eventEmitter) Emit(name string, payload ...interface{}) (handled bool) { - e.eventsMutex.Lock() - defer e.eventsMutex.Unlock() - if _, ok := e.events[name]; !ok { - return + eventRegister struct { + sync.Mutex + listeners []listener } - - if len(e.events[name].once) > 0 || len(e.events[name].on) > 0 { - handled = true + listener struct { + handler interface{} + once bool } +) - payloadV := make([]reflect.Value, 0) - - for _, p := range payload { - payloadV = append(payloadV, reflect.ValueOf(p)) - } +func (e *eventEmitter) Emit(name string, payload ...interface{}) (hasListener bool) { + e.eventsMutex.Lock() + e.init() - callHandlers := func(handlers []interface{}) { - for _, handler := range handlers { - handlerV := reflect.ValueOf(handler) - handlerV.Call(payloadV[:int(math.Min(float64(handlerV.Type().NumIn()), float64(len(payloadV))))]) - } + evt, ok := e.events[name] + if !ok { + e.eventsMutex.Unlock() + return } - - callHandlers(e.events[name].on) - callHandlers(e.events[name].once) - - e.events[name].once = make([]interface{}, 0) - return + e.eventsMutex.Unlock() + return evt.callHandlers(payload...) > 0 } func (e *eventEmitter) Once(name string, handler interface{}) { @@ -67,60 +56,97 @@ func (e *eventEmitter) On(name string, handler interface{}) { func (e *eventEmitter) RemoveListener(name string, handler interface{}) { e.eventsMutex.Lock() defer e.eventsMutex.Unlock() - if _, ok := e.events[name]; !ok { - return - } - handlerPtr := reflect.ValueOf(handler).Pointer() - - onHandlers := []interface{}{} - for idx := range e.events[name].on { - eventPtr := reflect.ValueOf(e.events[name].on[idx]).Pointer() - if eventPtr != handlerPtr { - onHandlers = append(onHandlers, e.events[name].on[idx]) - } - } - e.events[name].on = onHandlers + e.init() - onceHandlers := []interface{}{} - for idx := range e.events[name].once { - eventPtr := reflect.ValueOf(e.events[name].once[idx]).Pointer() - if eventPtr != handlerPtr { - onceHandlers = append(onceHandlers, e.events[name].once[idx]) - } + if evt, ok := e.events[name]; ok { + evt.Lock() + defer evt.Unlock() + evt.removeHandler(handler) } - - e.events[name].once = onceHandlers } // ListenerCount count the listeners by name, count all if name is empty func (e *eventEmitter) ListenerCount(name string) int { - count := 0 e.eventsMutex.Lock() - for key := range e.events { - if name == "" || name == key { - count += len(e.events[key].on) + len(e.events[key].once) + defer e.eventsMutex.Unlock() + e.init() + + if name != "" { + evt, ok := e.events[name] + if !ok { + return 0 } + return evt.count() } - e.eventsMutex.Unlock() + + count := 0 + for key := range e.events { + count += e.events[key].count() + } + return count } func (e *eventEmitter) addEvent(name string, handler interface{}, once bool) { e.eventsMutex.Lock() + defer e.eventsMutex.Unlock() + e.init() + if _, ok := e.events[name]; !ok { e.events[name] = &eventRegister{ - on: make([]interface{}, 0), - once: make([]interface{}, 0), + listeners: make([]listener, 0), } } - if once { - e.events[name].once = append(e.events[name].once, handler) - } else { - e.events[name].on = append(e.events[name].on, handler) + e.events[name].addHandler(handler, once) +} + +func (e *eventEmitter) init() { + if !e.hasInit { + e.events = make(map[string]*eventRegister, 0) + e.hasInit = true } - e.eventsMutex.Unlock() } -func (e *eventEmitter) initEventEmitter() { - e.events = make(map[string]*eventRegister) +func (er *eventRegister) addHandler(handler interface{}, once bool) { + er.Lock() + defer er.Unlock() + er.listeners = append(er.listeners, listener{handler: handler, once: once}) +} + +func (er *eventRegister) count() int { + er.Lock() + defer er.Unlock() + return len(er.listeners) +} + +func (e *eventRegister) removeHandler(handler interface{}) { + handlerPtr := reflect.ValueOf(handler).Pointer() + + e.listeners = slices.DeleteFunc(e.listeners, func(l listener) bool { + return reflect.ValueOf(l.handler).Pointer() == handlerPtr + }) +} + +func (er *eventRegister) callHandlers(payloads ...interface{}) int { + payloadV := make([]reflect.Value, 0) + + for _, p := range payloads { + payloadV = append(payloadV, reflect.ValueOf(p)) + } + + handle := func(l listener) { + handlerV := reflect.ValueOf(l.handler) + handlerV.Call(payloadV[:int(math.Min(float64(handlerV.Type().NumIn()), float64(len(payloadV))))]) + } + + er.Lock() + defer er.Unlock() + count := len(er.listeners) + for _, l := range er.listeners { + if l.once { + defer er.removeHandler(l.handler) + } + handle(l) + } + return count } diff --git a/vendor/github.com/playwright-community/playwright-go/fetch.go b/vendor/github.com/playwright-community/playwright-go/fetch.go index aff312778..89ca51872 100644 --- a/vendor/github.com/playwright-community/playwright-go/fetch.go +++ b/vendor/github.com/playwright-community/playwright-go/fetch.go @@ -16,6 +16,14 @@ type apiRequestImpl struct { func (r *apiRequestImpl) NewContext(options ...APIRequestNewContextOptions) (APIRequestContext, error) { overrides := map[string]interface{}{} if len(options) == 1 { + if options[0].ClientCertificates != nil { + certs, err := transformClientCertificate(options[0].ClientCertificates) + if err != nil { + return nil, err + } + overrides["clientCertificates"] = certs + options[0].ClientCertificates = nil + } if options[0].ExtraHttpHeaders != nil { overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders) options[0].ExtraHttpHeaders = nil @@ -37,7 +45,7 @@ func (r *apiRequestImpl) NewContext(options ...APIRequestNewContextOptions) (API channel, err := r.channel.Send("newRequest", options, overrides) if err != nil { - return nil, fmt.Errorf("could not send message: %w", err) + return nil, err } return fromChannel(channel).(*apiRequestContextImpl), nil } @@ -48,11 +56,20 @@ func newApiRequestImpl(pw *Playwright) *apiRequestImpl { type apiRequestContextImpl struct { channelOwner - tracing *tracingImpl + tracing *tracingImpl + closeReason *string } -func (r *apiRequestContextImpl) Dispose() error { - _, err := r.channel.Send("dispose") +func (r *apiRequestContextImpl) Dispose(options ...APIRequestContextDisposeOptions) error { + if len(options) == 1 { + r.closeReason = options[0].Reason + } + _, err := r.channel.Send("dispose", map[string]interface{}{ + "reason": r.closeReason, + }) + if errors.Is(err, ErrTargetClosed) { + return nil + } return err } @@ -82,6 +99,9 @@ func (r *apiRequestContextImpl) Fetch(urlOrRequest interface{}, options ...APIRe } func (r *apiRequestContextImpl) innerFetch(url string, request Request, options ...APIRequestContextFetchOptions) (APIResponse, error) { + if r.closeReason != nil { + return nil, fmt.Errorf("%w: %s", ErrTargetClosed, *r.closeReason) + } overrides := map[string]interface{}{} if url != "" { overrides["url"] = url @@ -93,6 +113,9 @@ func (r *apiRequestContextImpl) innerFetch(url string, request Request, options if options[0].MaxRedirects != nil && *options[0].MaxRedirects < 0 { return nil, errors.New("maxRedirects must be non-negative") } + if options[0].MaxRetries != nil && *options[0].MaxRetries < 0 { + return nil, errors.New("maxRetries must be non-negative") + } // only one of them can be specified if countNonNil(options[0].Data, options[0].Form, options[0].Multipart) > 1 { return nil, errors.New("only one of 'data', 'form' or 'multipart' can be specified") @@ -117,7 +140,15 @@ func (r *apiRequestContextImpl) innerFetch(url string, request Request, options case string: headersArray, ok := overrides["headers"].([]map[string]string) if ok && isJsonContentType(headersArray) { - overrides["jsonData"] = v + if json.Valid([]byte(v)) { + overrides["jsonData"] = v + } else { + data, err := json.Marshal(v) + if err != nil { + return nil, fmt.Errorf("could not marshal data: %w", err) + } + overrides["jsonData"] = string(data) + } } else { overrides["postData"] = base64.StdEncoding.EncodeToString([]byte(v)) } @@ -298,7 +329,7 @@ func (r *apiResponseImpl) Body() ([]byte, error) { }, }) if err != nil { - if isSafeCloseError(err) { + if errors.Is(err, ErrTargetClosed) { return nil, errors.New("response has been disposed") } return nil, err @@ -404,7 +435,6 @@ func isJsonContentType(headers []map[string]string) bool { } } } - } return false } diff --git a/vendor/github.com/playwright-community/playwright-go/file_chooser.go b/vendor/github.com/playwright-community/playwright-go/file_chooser.go index 390ffd572..119e88588 100644 --- a/vendor/github.com/playwright-community/playwright-go/file_chooser.go +++ b/vendor/github.com/playwright-community/playwright-go/file_chooser.go @@ -28,7 +28,7 @@ type InputFile struct { Buffer []byte `json:"buffer"` } -func (f *fileChooserImpl) SetFiles(files []InputFile, options ...FileChooserSetFilesOptions) error { +func (f *fileChooserImpl) SetFiles(files interface{}, options ...FileChooserSetFilesOptions) error { if len(options) == 1 { return f.elementHandle.SetInputFiles(files, ElementHandleSetInputFilesOptions(options[0])) } diff --git a/vendor/github.com/playwright-community/playwright-go/frame.go b/vendor/github.com/playwright-community/playwright-go/frame.go index cd8e508d2..dfd342e23 100644 --- a/vendor/github.com/playwright-community/playwright-go/frame.go +++ b/vendor/github.com/playwright-community/playwright-go/frame.go @@ -4,46 +4,47 @@ import ( "errors" "fmt" "os" - "sync" "time" + + mapset "github.com/deckarep/golang-set/v2" ) type frameImpl struct { channelOwner - sync.RWMutex detached bool page *pageImpl name string url string parentFrame Frame childFrames []Frame - loadStates *safeStringSet + loadStates mapset.Set[string] } func newFrame(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *frameImpl { - var loadStates *safeStringSet + var loadStates mapset.Set[string] + if ls, ok := initializer["loadStates"].([]string); ok { - loadStates = newSafeStringSet(ls) + loadStates = mapset.NewSet[string](ls...) } else { - loadStates = newSafeStringSet([]string{}) + loadStates = mapset.NewSet[string]() } - bt := &frameImpl{ + f := &frameImpl{ name: initializer["name"].(string), url: initializer["url"].(string), loadStates: loadStates, childFrames: make([]Frame, 0), } - bt.createChannelOwner(bt, parent, objectType, guid, initializer) + f.createChannelOwner(f, parent, objectType, guid, initializer) channelOwner := fromNullableChannel(initializer["parentFrame"]) if channelOwner != nil { - bt.parentFrame = channelOwner.(*frameImpl) - bt.parentFrame.(*frameImpl).childFrames = append(bt.parentFrame.(*frameImpl).childFrames, bt) + f.parentFrame = channelOwner.(*frameImpl) + f.parentFrame.(*frameImpl).childFrames = append(f.parentFrame.(*frameImpl).childFrames, f) } - bt.channel.On("navigated", bt.onFrameNavigated) - bt.channel.On("loadstate", bt.onLoadState) - return bt + f.channel.On("navigated", f.onFrameNavigated) + f.channel.On("loadstate", f.onLoadState) + return f } func (f *frameImpl) URL() string { @@ -78,7 +79,7 @@ func (f *frameImpl) Goto(url string, options ...FrameGotoOptions) (Response, err "url": url, }, options) if err != nil { - return nil, err + return nil, fmt.Errorf("Frame.Goto %s: %w", url, err) } channelOwner := fromNullableChannel(channel) if channelOwner == nil { @@ -136,7 +137,7 @@ func (f *frameImpl) WaitForLoadState(options ...FrameWaitForLoadStateOptions) er } func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func() error) error { - if f.loadStates.Has(state) { + if f.loadStates.ContainsOne(state) { return nil } waiter, err := f.setNavigationWaiter(timeout) @@ -206,8 +207,11 @@ func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavi } predicate := func(events ...interface{}) bool { ev := events[0].(map[string]interface{}) - if ev["error"] != nil { - print("error") + err, ok := ev["error"] + if ok { + // Any failed navigation results in a rejection. + logger.Printf("navigated to %s error: %v", ev["url"].(string), err) + return true } return matcher == nil || matcher.Matches(ev["url"].(string)) } @@ -246,7 +250,7 @@ func (f *frameImpl) setNavigationWaiter(timeout *float64) (*waiter, error) { } else { waiter.WithTimeout(f.page.timeoutSettings.NavigationTimeout()) } - waiter.RejectOnEvent(f.page, "close", fmt.Errorf("Navigation failed because page was closed!")) + waiter.RejectOnEvent(f.page, "close", f.page.closeErrorWithReason()) waiter.RejectOnEvent(f.page, "crash", fmt.Errorf("Navigation failed because page crashed!")) waiter.RejectOnEvent(f.page, "framedetached", fmt.Errorf("Navigating frame was detached!"), func(payload interface{}) bool { frame, ok := payload.(*frameImpl) @@ -452,11 +456,13 @@ func (f *frameImpl) Hover(selector string, options ...FrameHoverOptions) error { return err } -func (f *frameImpl) SetInputFiles(selector string, files []InputFile, options ...FrameSetInputFilesOptions) error { - _, err := f.channel.Send("setInputFiles", map[string]interface{}{ - "selector": selector, - "files": normalizeFilePayloads(files), - }, options) +func (f *frameImpl) SetInputFiles(selector string, files interface{}, options ...FrameSetInputFilesOptions) error { + params, err := convertInputFiles(files, f.page.browserContext) + if err != nil { + return err + } + params.Selector = &selector + _, err = f.channel.Send("setInputFiles", params, options) return err } diff --git a/vendor/github.com/playwright-community/playwright-go/frame_locator.go b/vendor/github.com/playwright-community/playwright-go/frame_locator.go index c5a883723..3bb579489 100644 --- a/vendor/github.com/playwright-community/playwright-go/frame_locator.go +++ b/vendor/github.com/playwright-community/playwright-go/frame_locator.go @@ -120,3 +120,7 @@ func (fl *frameLocatorImpl) Locator(selectorOrLocator interface{}, options ...Fr func (fl *frameLocatorImpl) Nth(index int) FrameLocator { return newFrameLocator(fl.frame, fl.frameSelector+" >> nth="+strconv.Itoa(index)) } + +func (fl *frameLocatorImpl) Owner() Locator { + return newLocator(fl.frame, fl.frameSelector) +} diff --git a/vendor/github.com/playwright-community/playwright-go/generated-enums.go b/vendor/github.com/playwright-community/playwright-go/generated-enums.go index 71fd048eb..0ad547947 100644 --- a/vendor/github.com/playwright-community/playwright-go/generated-enums.go +++ b/vendor/github.com/playwright-community/playwright-go/generated-enums.go @@ -235,6 +235,19 @@ var ( RouteFromHarUpdateContentPolicyAttach = getRouteFromHarUpdateContentPolicy("attach") ) +func getUnrouteBehavior(in string) *UnrouteBehavior { + v := UnrouteBehavior(in) + return &v +} + +type UnrouteBehavior string + +var ( + UnrouteBehaviorWait *UnrouteBehavior = getUnrouteBehavior("wait") + UnrouteBehaviorIgnoreErrors = getUnrouteBehavior("ignoreErrors") + UnrouteBehaviorDefault = getUnrouteBehavior("default") +) + func getMouseButton(in string) *MouseButton { v := MouseButton(in) return &v @@ -256,10 +269,11 @@ func getKeyboardModifier(in string) *KeyboardModifier { type KeyboardModifier string var ( - KeyboardModifierAlt *KeyboardModifier = getKeyboardModifier("Alt") - KeyboardModifierControl = getKeyboardModifier("Control") - KeyboardModifierMeta = getKeyboardModifier("Meta") - KeyboardModifierShift = getKeyboardModifier("Shift") + KeyboardModifierAlt *KeyboardModifier = getKeyboardModifier("Alt") + KeyboardModifierControl = getKeyboardModifier("Control") + KeyboardModifierControlOrMeta = getKeyboardModifier("ControlOrMeta") + KeyboardModifierMeta = getKeyboardModifier("Meta") + KeyboardModifierShift = getKeyboardModifier("Shift") ) func getScreenshotAnimations(in string) *ScreenshotAnimations { @@ -363,3 +377,15 @@ var ( MediaPrint = getMedia("print") MediaNoOverride = getMedia("no-override") ) + +func getHttpCredentialsSend(in string) *HttpCredentialsSend { + v := HttpCredentialsSend(in) + return &v +} + +type HttpCredentialsSend string + +var ( + HttpCredentialsSendUnauthorized *HttpCredentialsSend = getHttpCredentialsSend("unauthorized") + HttpCredentialsSendAlways = getHttpCredentialsSend("always") +) diff --git a/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go b/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go index 5ec04d416..6354f1ca8 100644 --- a/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go +++ b/vendor/github.com/playwright-community/playwright-go/generated-interfaces.go @@ -32,13 +32,12 @@ type APIRequestContext interface { Delete(url string, options ...APIRequestContextDeleteOptions) (APIResponse, error) // All responses returned by [APIRequestContext.Get] and similar methods are stored in the memory, so that you can - // later call [APIResponse.Body]. This method discards all stored responses, and makes [APIResponse.Body] throw - // "Response disposed" error. - Dispose() error + // later call [APIResponse.Body].This method discards all its resources, calling any method on disposed + // [APIRequestContext] will throw an exception. + Dispose(options ...APIRequestContextDisposeOptions) error // Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and - // update context cookies from the response. The method will automatically follow redirects. JSON objects can be - // passed directly to the request. + // update context cookies from the response. The method will automatically follow redirects. // // urlOrRequest: Target URL or Request to get all parameters from. Fetch(urlOrRequest interface{}, options ...APIRequestContextFetchOptions) (APIResponse, error) @@ -104,8 +103,8 @@ type APIResponse interface { // An object with all the response HTTP headers associated with this response. Headers() map[string]string - // An array with all the request HTTP headers associated with this response. Header names are not lower-cased. Headers - // with multiple entries, such as `Set-Cookie`, appear in the array multiple times. + // An array with all the response HTTP headers associated with this response. Header names are not lower-cased. + // Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times. HeadersArray() []NameValue // Returns the JSON representation of response body. @@ -139,7 +138,7 @@ type APIResponseAssertions interface { ToBeOK() error } -// A Browser is created via [BrowserType.Launch]. An example of using a [Browser] to create a [Page]: +// A Browser is created via [BrowserType.Launch]. An example of using a [Browser] to create a [Page]: type Browser interface { EventEmitter // Emitted when Browser gets disconnected from the browser application. This might happen because of one of the @@ -158,7 +157,7 @@ type Browser interface { // **NOTE** This is similar to force quitting the browser. Therefore, you should call [BrowserContext.Close] on any // [BrowserContext]'s you explicitly created earlier with [Browser.NewContext] **before** calling [Browser.Close]. // The [Browser] object itself is considered to be disposed and cannot be used anymore. - Close() error + Close(options ...BrowserCloseOptions) error // Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts. Contexts() []BrowserContext @@ -210,21 +209,27 @@ type Browser interface { Version() string } -// BrowserContexts provide a way to operate multiple independent browser sessions. +// BrowserContexts provide a way to operate multiple independent browser sessions. // If a page opens another page, e.g. with a `window.open` call, the popup will belong to the parent page's browser // context. -// Playwright allows creating "incognito" browser contexts with [Browser.NewContext] method. "Incognito" browser -// contexts don't write any browsing data to disk. +// Playwright allows creating isolated non-persistent browser contexts with [Browser.NewContext] method. +// Non-persistent browser contexts don't write any browsing data to disk. type BrowserContext interface { EventEmitter + // **NOTE** Only works with Chromium browser's persistent context. + // Emitted when new background page is created in the context. + OnBackgroundPage(fn func(Page)) + + // Playwright has ability to mock clock and passage of time. + Clock() Clock + // Emitted when Browser context gets closed. This might happen because of one of the following: // - Browser context is closed. // - Browser application is closed or crashed. // - The [Browser.Close] method was called. OnClose(fn func(BrowserContext)) - // Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. Also - // emitted if the page throws an error or a warning. + // Emitted when JavaScript within the page calls one of console API methods, e.g. `console.log` or `console.dir`. // The arguments passed into `console.log` and the page are available on the [ConsoleMessage] event handler argument. OnConsole(fn func(ConsoleMessage)) @@ -240,7 +245,9 @@ type BrowserContext interface { // will also fire for popup pages. See also [Page.OnPopup] to receive events about popups relevant to a specific page. // The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a // popup with `window.open('http://example.com')`, this event will fire when the network request to - // "http://example.com" is done and its response has started loading in the popup. + // "http://example.com" is done and its response has started loading in the popup. If you would like to route/listen + // to this network request, use [BrowserContext.Route] and [BrowserContext.OnRequest] respectively instead of similar + // methods on the [Page]. // **NOTE** Use [Page.WaitForLoadState] to wait until the page gets to a particular state (you should not need it in // most cases). OnPage(fn func(Page)) @@ -272,10 +279,6 @@ type BrowserContext interface { // Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies // can be obtained via [BrowserContext.Cookies]. - // - // cookies: Adds cookies to the browser context. - // - // For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". AddCookies(cookies []OptionalCookie) error // Adds a script which would be evaluated in one of the following scenarios: @@ -295,15 +298,15 @@ type BrowserContext interface { // Returns the browser instance of the context. If it was launched as a persistent context null gets returned. Browser() Browser - // Clears context cookies. - ClearCookies() error + // Removes cookies from context. Accepts optional filter. + ClearCookies(options ...BrowserContextClearCookiesOptions) error // Clears all permission overrides for the browser context. ClearPermissions() error // Closes the browser context. All the pages that belong to the browser context will be closed. // **NOTE** The default browser context cannot be closed. - Close() error + Close(options ...BrowserContextCloseOptions) error // If no URLs are specified, this method returns all cookies. If URLs are specified, only cookies that affect those // URLs are returned. @@ -333,21 +336,22 @@ type BrowserContext interface { // specified. // // permissions: A permission or an array of permissions to grant. Permissions can be one of the following values: - // - `'geolocation'` - // - `'midi'` - // - `'midi-sysex'` (system-exclusive midi) - // - `'notifications'` - // - `'camera'` - // - `'microphone'` - // - `'background-sync'` - // - `'ambient-light-sensor'` // - `'accelerometer'` - // - `'gyroscope'` - // - `'magnetometer'` // - `'accessibility-events'` + // - `'ambient-light-sensor'` + // - `'background-sync'` + // - `'camera'` // - `'clipboard-read'` // - `'clipboard-write'` + // - `'geolocation'` + // - `'gyroscope'` + // - `'magnetometer'` + // - `'microphone'` + // - `'midi-sysex'` (system-exclusive midi) + // - `'midi'` + // - `'notifications'` // - `'payment-handler'` + // - `'storage-access'` GrantPermissions(permissions []string, options ...BrowserContextGrantPermissionsOptions) error // **NOTE** CDP sessions are only supported on Chromium-based browsers. @@ -437,6 +441,9 @@ type BrowserContext interface { Tracing() Tracing + // Removes all routes created with [BrowserContext.Route] and [BrowserContext.RouteFromHAR]. + UnrouteAll(options ...BrowserContextUnrouteAllOptions) error + // Removes a route created with [BrowserContext.Route]. When β€œhandler” is not specified, removes all routes for the // β€œurl”. // @@ -514,14 +521,15 @@ type BrowserType interface { Name() string } -// The `CDPSession` instances are used to talk raw Chrome Devtools Protocol: -// - protocol methods can be called with `session.send` method. -// - protocol events can be subscribed to with `session.on` method. +// The `CDPSession` instances are used to talk raw Chrome Devtools Protocol: +// - protocol methods can be called with `session.send` method. +// - protocol events can be subscribed to with `session.on` method. +// // Useful links: -// - Documentation on DevTools Protocol can be found here: -// [DevTools Protocol Viewer]. -// - Getting Started with DevTools Protocol: -// https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md +// - Documentation on DevTools Protocol can be found here: +// [DevTools Protocol Viewer]. +// - Getting Started with DevTools Protocol: +// https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md // // [DevTools Protocol Viewer]: https://chromedevtools.github.io/devtools-protocol/ type CDPSession interface { @@ -536,7 +544,65 @@ type CDPSession interface { Send(method string, params map[string]interface{}) (interface{}, error) } -// [ConsoleMessage] objects are dispatched by page via the [Page.OnConsole] event. For each console messages logged in +// Accurately simulating time-dependent behavior is essential for verifying the correctness of applications. Learn +// more about [clock emulation]. +// Note that clock is installed for the entire [BrowserContext], so the time in all the pages and iframes is +// controlled by the same clock. +// +// [clock emulation]: https://playwright.dev/docs/clock +type Clock interface { + // Advance the clock by jumping forward in time. Only fires due timers at most once. This is equivalent to user + // closing the laptop lid for a while and reopening it later, after given time. + // + // ticks: Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are + // "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds. + FastForward(ticks interface{}) error + + // Install fake implementations for the following time-related functions: + // - `Date` + // - `setTimeout` + // - `clearTimeout` + // - `setInterval` + // - `clearInterval` + // - `requestAnimationFrame` + // - `cancelAnimationFrame` + // - `requestIdleCallback` + // - `cancelIdleCallback` + // - `performance` + // Fake timers are used to manually control the flow of time in tests. They allow you to advance time, fire timers, + // and control the behavior of time-dependent functions. See [Clock.RunFor] and [Clock.FastForward] for more + // information. + Install(options ...ClockInstallOptions) error + + // Advance the clock, firing all the time-related callbacks. + // + // ticks: Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are + // "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds. + RunFor(ticks interface{}) error + + // Advance the clock by jumping forward in time and pause the time. Once this method is called, no timers are fired + // unless [Clock.RunFor], [Clock.FastForward], [Clock.PauseAt] or [Clock.Resume] is called. + // Only fires due timers at most once. This is equivalent to user closing the laptop lid for a while and reopening it + // at the specified time and pausing. + // + // time: Time to pause at. + PauseAt(time interface{}) error + + // Resumes timers. Once this method is called, time resumes flowing, timers are fired as usual. + Resume() error + + // Makes `Date.now` and `new Date()` return fixed fake time at all times, keeps all the timers running. + // + // time: Time to be set. + SetFixedTime(time interface{}) error + + // Sets current system time but does not trigger any timers. + // + // time: Time to be set. + SetSystemTime(time interface{}) error +} + +// [ConsoleMessage] objects are dispatched by page via the [Page.OnConsole] event. For each console message logged in // the page there will be corresponding event in the Playwright context. type ConsoleMessage interface { // List of arguments passed to a `console` function call. See also [Page.OnConsole]. @@ -604,8 +670,8 @@ type Download interface { // Get the page that the download belongs to. Page() Page - // Returns path to the downloaded file in case of successful download. The method will wait for the download to finish - // if necessary. The method throws when connected remotely. + // Returns path to the downloaded file for a successful download, or throws for a failed/canceled download. The method + // will wait for the download to finish if necessary. The method throws when connected remotely. // Note that the download's file name is a random GUID, use [Download.SuggestedFilename] to get suggested file name. Path() (string, error) @@ -630,7 +696,8 @@ type Download interface { String() string } -// ElementHandle represents an in-page DOM element. ElementHandles can be created with the [Page.QuerySelector] +// ElementHandle represents an in-page DOM element. ElementHandles can be created with the [Page.QuerySelector] +// // method. // **NOTE** The use of ElementHandle is discouraged, use [Locator] objects and web-first assertions instead. // ElementHandle prevents DOM element from garbage collection unless the handle is disposed with [JSHandle.Dispose]. @@ -665,13 +732,15 @@ type ElementHandle interface { // 2. Wait for [actionability] checks on the element, unless β€œforce” option is set. // 3. Scroll the element into view if needed. // 4. Use [Page.Mouse] to click in the center of the element. - // 5. Wait for initiated navigations to either succeed or fail, unless β€œnoWaitAfter” option is set. - // 6. Ensure that the element is now checked. If not, this method throws. + // 5. Ensure that the element is now checked. If not, this method throws. // If the element is detached from the DOM at any moment during the action, this method throws. // When all steps combined have not finished during the specified β€œtimeout”, this method throws a [TimeoutError]. // Passing zero timeout disables this. // + // Deprecated: Use locator-based [Locator.Check] instead. Read more about [locators]. + // // [actionability]: https://playwright.dev/docs/actionability + // [locators]: https://playwright.dev/docs/locators Check(options ...ElementHandleCheckOptions) error // This method clicks the element by performing the following steps: @@ -683,7 +752,10 @@ type ElementHandle interface { // When all steps combined have not finished during the specified β€œtimeout”, this method throws a [TimeoutError]. // Passing zero timeout disables this. // + // Deprecated: Use locator-based [Locator.Click] instead. Read more about [locators]. + // // [actionability]: https://playwright.dev/docs/actionability + // [locators]: https://playwright.dev/docs/locators Click(options ...ElementHandleClickOptions) error // Returns the content frame for element handles referencing iframe nodes, or `null` otherwise @@ -693,31 +765,38 @@ type ElementHandle interface { // 1. Wait for [actionability] checks on the element, unless β€œforce” option is set. // 2. Scroll the element into view if needed. // 3. Use [Page.Mouse] to double click in the center of the element, or the specified β€œposition”. - // 4. Wait for initiated navigations to either succeed or fail, unless β€œnoWaitAfter” option is set. Note that if - // the first click of the `dblclick()` triggers a navigation event, this method will throw. // If the element is detached from the DOM at any moment during the action, this method throws. // When all steps combined have not finished during the specified β€œtimeout”, this method throws a [TimeoutError]. // Passing zero timeout disables this. // **NOTE** `elementHandle.dblclick()` dispatches two `click` events and a single `dblclick` event. // + // Deprecated: Use locator-based [Locator.Dblclick] instead. Read more about [locators]. + // // [actionability]: https://playwright.dev/docs/actionability + // [locators]: https://playwright.dev/docs/locators Dblclick(options ...ElementHandleDblclickOptions) error // The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element, // `click` is dispatched. This is equivalent to calling // [element.Click()]. // + // Deprecated: Use locator-based [Locator.DispatchEvent] instead. Read more about [locators]. + // // 1. typ: DOM event type: `"click"`, `"dragstart"`, etc. // 2. eventInit: Optional event-specific initialization properties. // // [element.Click()]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click + // [DeviceMotionEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent + // [DeviceOrientationEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent // [DragEvent]: https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent + // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event // [FocusEvent]: https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent // [KeyboardEvent]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent // [MouseEvent]: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent // [PointerEvent]: https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent // [TouchEvent]: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent - // [Event]: https://developer.mozilla.org/en-US/docs/Web/API/Event/Event + // [WheelEvent]: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent + // [locators]: https://playwright.dev/docs/locators DispatchEvent(typ string, eventInit ...interface{}) error // Returns the return value of β€œexpression”. @@ -726,6 +805,8 @@ type ElementHandle interface { // If β€œexpression” returns a [Promise], then [ElementHandle.EvalOnSelector] would wait for the promise to resolve and // return its value. // + // Deprecated: This method does not wait for the element to pass actionability checks and therefore can lead to the flaky tests. Use [Locator.Evaluate], other [Locator] helper methods or web-first assertions instead. + // // 1. selector: A selector to query for. // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the // function is automatically invoked. @@ -738,6 +819,8 @@ type ElementHandle interface { // If β€œexpression” returns a [Promise], then [ElementHandle.EvalOnSelectorAll] would wait for the promise to resolve // and return its value. // + // Deprecated: In most cases, [Locator.EvaluateAll], other [Locator] helper methods and web-first assertions do a better job. + // // 1. selector: A selector to query for. // 2. expression: JavaScript expression to be evaluated in the browser context. If the expression evaluates to a function, the // function is automatically invoked. @@ -752,38 +835,58 @@ type ElementHandle interface { // instead. // To send fine-grained keyboard events, use [Locator.PressSequentially]. // + // Deprecated: Use locator-based [Locator.Fill] instead. Read more about [locators]. + // // value: Value to set for the ``, `